diff --git a/exporter/opentelemetry-exporter-datadog/CHANGELOG.md b/exporter/opentelemetry-exporter-datadog/CHANGELOG.md
deleted file mode 100644
index b7308e8e5f9..00000000000
--- a/exporter/opentelemetry-exporter-datadog/CHANGELOG.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.15b0
-
-Released 2020-11-02
-
- - Make `SpanProcessor.on_start` accept parent Context
- ([#1251](https://github.com/open-telemetry/opentelemetry-python/pull/1251))
-
-## Version 0.14b0
-
-Released 2020-10-13
-
-- Add support for span resource labels and service name
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-exporter-datadog
- ([#953](https://github.com/open-telemetry/opentelemetry-python/pull/953))
-
-## 0.8b0
-
-Released 2020-05-27
-
-- Add exporter to Datadog
- ([#572](https://github.com/open-telemetry/opentelemetry-python/pull/572))
-
diff --git a/exporter/opentelemetry-exporter-datadog/README.rst b/exporter/opentelemetry-exporter-datadog/README.rst
deleted file mode 100644
index cb97e5997fe..00000000000
--- a/exporter/opentelemetry-exporter-datadog/README.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-OpenTelemetry Datadog Exporter
-==============================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-exporter-datadog.svg
- :target: https://pypi.org/project/opentelemetry-exporter-datadog/
-
-This library allows to export tracing data to `Datadog
-`_. OpenTelemetry span event and links are not
-supported.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-exporter-datadog
-
-
-.. _Datadog: https://www.datadoghq.com/
-.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/
-
-
-References
-----------
-
-* `Datadog `_
-* `OpenTelemetry Project `_
diff --git a/exporter/opentelemetry-exporter-datadog/setup.cfg b/exporter/opentelemetry-exporter-datadog/setup.cfg
deleted file mode 100644
index 45bf200ee45..00000000000
--- a/exporter/opentelemetry-exporter-datadog/setup.cfg
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-exporter-datadog
-description = Datadog Span Exporter for OpenTelemetry
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/exporter/opentelemetry-exporter-datadog
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- ddtrace>=0.34.0
- opentelemetry-api == 0.16.dev0
- opentelemetry-sdk == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.extras_require]
-test =
diff --git a/exporter/opentelemetry-exporter-datadog/setup.py b/exporter/opentelemetry-exporter-datadog/setup.py
deleted file mode 100644
index 0c3bdf453fd..00000000000
--- a/exporter/opentelemetry-exporter-datadog/setup.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "exporter", "datadog", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/__init__.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/__init__.py
deleted file mode 100644
index 3294ba4e4e0..00000000000
--- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/__init__.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-The **OpenTelemetry Datadog Exporter** provides a span exporter from
-`OpenTelemetry`_ traces to `Datadog`_ by using the Datadog Agent.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-exporter-datadog
-
-
-Usage
------
-
-The Datadog exporter provides a span processor that must be added along with the
-exporter. In addition, a formatter is provided to handle propagation of trace
-context between OpenTelemetry-instrumented and Datadog-instrumented services in
-a distributed trace.
-
-.. code:: python
-
- from opentelemetry import propagators, trace
- from opentelemetry.exporter.datadog import DatadogExportSpanProcessor, DatadogSpanExporter
- from opentelemetry.exporter.datadog.propagator import DatadogFormat
- from opentelemetry.sdk.trace import TracerProvider
-
- trace.set_tracer_provider(TracerProvider())
- tracer = trace.get_tracer(__name__)
-
- exporter = DatadogSpanExporter(
- agent_url="http://agent:8126", service="my-helloworld-service"
- )
-
- span_processor = DatadogExportSpanProcessor(exporter)
- trace.get_tracer_provider().add_span_processor(span_processor)
-
- # Optional: use Datadog format for propagation in distributed traces
- propagators.set_global_textmap(DatadogFormat())
-
- with tracer.start_as_current_span("foo"):
- print("Hello world!")
-
-
-Examples
---------
-
-The `docs/examples/datadog_exporter`_ includes examples for using the Datadog
-exporter with OpenTelemetry instrumented applications.
-
-API
----
-.. _Datadog: https://www.datadoghq.com/
-.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/
-.. _docs/examples/datadog_exporter: https://github.com/open-telemetry/opentelemetry-python/tree/master/docs/examples/datadog_exporter
-"""
-# pylint: disable=import-error
-
-from .exporter import DatadogSpanExporter
-from .spanprocessor import DatadogExportSpanProcessor
-
-__all__ = ["DatadogExportSpanProcessor", "DatadogSpanExporter"]
diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/constants.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/constants.py
deleted file mode 100644
index 2ae5386e848..00000000000
--- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/constants.py
+++ /dev/null
@@ -1,9 +0,0 @@
-DD_ORIGIN = "_dd_origin"
-AUTO_REJECT = 0
-AUTO_KEEP = 1
-USER_KEEP = 2
-SAMPLE_RATE_METRIC_KEY = "_sample_rate"
-SAMPLING_PRIORITY_KEY = "_sampling_priority_v1"
-ENV_KEY = "env"
-VERSION_KEY = "version"
-SERVICE_NAME_TAG = "service.name"
diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py
deleted file mode 100644
index 2b1bd900417..00000000000
--- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py
+++ /dev/null
@@ -1,317 +0,0 @@
-# Copyright The OpenTelemetry 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
-import os
-from urllib.parse import urlparse
-
-from ddtrace.ext import SpanTypes as DatadogSpanTypes
-from ddtrace.internal.writer import AgentWriter
-from ddtrace.span import Span as DatadogSpan
-
-import opentelemetry.trace as trace_api
-from opentelemetry.sdk.trace import sampling
-from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
-
-# pylint:disable=relative-beyond-top-level
-from .constants import (
- DD_ORIGIN,
- ENV_KEY,
- SAMPLE_RATE_METRIC_KEY,
- SERVICE_NAME_TAG,
- VERSION_KEY,
-)
-
-logger = logging.getLogger(__name__)
-
-
-DEFAULT_AGENT_URL = "http://localhost:8126"
-_INSTRUMENTATION_SPAN_TYPES = {
- "opentelemetry.instrumentation.aiohttp-client": DatadogSpanTypes.HTTP,
- "opentelemetry.instrumentation.asgi": DatadogSpanTypes.WEB,
- "opentelemetry.instrumentation.dbapi": DatadogSpanTypes.SQL,
- "opentelemetry.instrumentation.django": DatadogSpanTypes.WEB,
- "opentelemetry.instrumentation.flask": DatadogSpanTypes.WEB,
- "opentelemetry.instrumentation.grpc": DatadogSpanTypes.GRPC,
- "opentelemetry.instrumentation.jinja2": DatadogSpanTypes.TEMPLATE,
- "opentelemetry.instrumentation.mysql": DatadogSpanTypes.SQL,
- "opentelemetry.instrumentation.psycopg2": DatadogSpanTypes.SQL,
- "opentelemetry.instrumentation.pymemcache": DatadogSpanTypes.CACHE,
- "opentelemetry.instrumentation.pymongo": DatadogSpanTypes.MONGODB,
- "opentelemetry.instrumentation.pymysql": DatadogSpanTypes.SQL,
- "opentelemetry.instrumentation.redis": DatadogSpanTypes.REDIS,
- "opentelemetry.instrumentation.requests": DatadogSpanTypes.HTTP,
- "opentelemetry.instrumentation.sqlalchemy": DatadogSpanTypes.SQL,
- "opentelemetry.instrumentation.wsgi": DatadogSpanTypes.WEB,
-}
-
-
-class DatadogSpanExporter(SpanExporter):
- """Datadog span exporter for OpenTelemetry.
-
- Args:
- agent_url: The url of the Datadog Agent or use ``DD_TRACE_AGENT_URL`` environment variable
- service: The service name to be used for the application or use ``DD_SERVICE`` environment variable
- env: Set the application’s environment or use ``DD_ENV`` environment variable
- version: Set the application’s version or use ``DD_VERSION`` environment variable
- tags: A list of default tags to be added to every span or use ``DD_TAGS`` environment variable
- """
-
- def __init__(
- self, agent_url=None, service=None, env=None, version=None, tags=None
- ):
- self.agent_url = (
- agent_url
- if agent_url
- else os.environ.get("DD_TRACE_AGENT_URL", DEFAULT_AGENT_URL)
- )
- self.service = service or os.environ.get("DD_SERVICE")
- self.env = env or os.environ.get("DD_ENV")
- self.version = version or os.environ.get("DD_VERSION")
- self.tags = _parse_tags_str(tags or os.environ.get("DD_TAGS"))
- self._agent_writer = None
-
- @property
- def agent_writer(self):
- if self._agent_writer is None:
- url_parsed = urlparse(self.agent_url)
- if url_parsed.scheme in ("http", "https"):
- self._agent_writer = AgentWriter(
- hostname=url_parsed.hostname,
- port=url_parsed.port,
- https=url_parsed.scheme == "https",
- )
- elif url_parsed.scheme == "unix":
- self._agent_writer = AgentWriter(uds_path=url_parsed.path)
- else:
- raise ValueError(
- "Unknown scheme `%s` for agent URL" % url_parsed.scheme
- )
- return self._agent_writer
-
- def export(self, spans):
- datadog_spans = self._translate_to_datadog(spans)
-
- self.agent_writer.write(spans=datadog_spans)
-
- return SpanExportResult.SUCCESS
-
- def shutdown(self):
- if self.agent_writer.started:
- self.agent_writer.stop()
- self.agent_writer.join(self.agent_writer.exit_timeout)
-
- # pylint: disable=too-many-locals
- def _translate_to_datadog(self, spans):
- datadog_spans = []
-
- for span in spans:
- trace_id, parent_id, span_id = _get_trace_ids(span)
-
- # datadog Span is initialized with a reference to the tracer which is
- # used to record the span when it is finished. We can skip ignore this
- # because we are not calling the finish method and explictly set the
- # duration.
- tracer = None
-
- # extract resource attributes to be used as tags as well as potential service name
- [
- resource_tags,
- resource_service_name,
- ] = _extract_tags_from_resource(span.resource)
-
- datadog_span = DatadogSpan(
- tracer,
- _get_span_name(span),
- service=resource_service_name or self.service,
- resource=_get_resource(span),
- span_type=_get_span_type(span),
- trace_id=trace_id,
- span_id=span_id,
- parent_id=parent_id,
- )
- datadog_span.start_ns = span.start_time
- datadog_span.duration_ns = span.end_time - span.start_time
-
- if not span.status.is_ok:
- datadog_span.error = 1
- if span.status.description:
- exc_type, exc_val = _get_exc_info(span)
- # no mapping for error.stack since traceback not recorded
- datadog_span.set_tag("error.msg", exc_val)
- datadog_span.set_tag("error.type", exc_type)
-
- # combine resource attributes and span attributes, don't modify existing span attributes
- combined_span_tags = {}
- combined_span_tags.update(resource_tags)
- combined_span_tags.update(span.attributes)
-
- datadog_span.set_tags(combined_span_tags)
-
- # add configured env tag
- if self.env is not None:
- datadog_span.set_tag(ENV_KEY, self.env)
-
- # add configured application version tag to only root span
- if self.version is not None and parent_id == 0:
- datadog_span.set_tag(VERSION_KEY, self.version)
-
- # add configured global tags
- datadog_span.set_tags(self.tags)
-
- # add origin to root span
- origin = _get_origin(span)
- if origin and parent_id == 0:
- datadog_span.set_tag(DD_ORIGIN, origin)
-
- sampling_rate = _get_sampling_rate(span)
- if sampling_rate is not None:
- datadog_span.set_metric(SAMPLE_RATE_METRIC_KEY, sampling_rate)
-
- # span events and span links are not supported
-
- datadog_spans.append(datadog_span)
-
- return datadog_spans
-
-
-def _get_trace_ids(span):
- """Extract tracer ids from span"""
- ctx = span.get_span_context()
- trace_id = ctx.trace_id
- span_id = ctx.span_id
-
- if isinstance(span.parent, trace_api.Span):
- parent_id = span.parent.get_span_context().span_id
- elif isinstance(span.parent, trace_api.SpanContext):
- parent_id = span.parent.span_id
- else:
- parent_id = 0
-
- trace_id = _convert_trace_id_uint64(trace_id)
-
- return trace_id, parent_id, span_id
-
-
-def _convert_trace_id_uint64(otel_id):
- """Convert 128-bit int used for trace_id to 64-bit unsigned int"""
- return otel_id & 0xFFFFFFFFFFFFFFFF
-
-
-def _get_span_name(span):
- """Get span name by using instrumentation and kind while backing off to
- span.name
- """
- instrumentation_name = (
- span.instrumentation_info.name if span.instrumentation_info else None
- )
- span_kind_name = span.kind.name if span.kind else None
- name = (
- "{}.{}".format(instrumentation_name, span_kind_name)
- if instrumentation_name and span_kind_name
- else span.name
- )
- return name
-
-
-def _get_resource(span):
- """Get resource name for span"""
- if "http.method" in span.attributes:
- route = span.attributes.get("http.route")
- return (
- span.attributes["http.method"] + " " + route
- if route
- else span.attributes["http.method"]
- )
-
- return span.name
-
-
-def _get_span_type(span):
- """Get Datadog span type"""
- instrumentation_name = (
- span.instrumentation_info.name if span.instrumentation_info else None
- )
- span_type = _INSTRUMENTATION_SPAN_TYPES.get(instrumentation_name)
- return span_type
-
-
-def _get_exc_info(span):
- """Parse span status description for exception type and value"""
- exc_type, exc_val = span.status.description.split(":", 1)
- return exc_type, exc_val.strip()
-
-
-def _get_origin(span):
- ctx = span.get_span_context()
- origin = ctx.trace_state.get(DD_ORIGIN)
- return origin
-
-
-def _get_sampling_rate(span):
- ctx = span.get_span_context()
- return (
- span.sampler.rate
- if ctx.trace_flags.sampled
- and isinstance(span.sampler, sampling.TraceIdRatioBased)
- else None
- )
-
-
-def _parse_tags_str(tags_str):
- """Parse a string of tags typically provided via environment variables.
-
- The expected string is of the form::
- "key1:value1,key2:value2"
-
- :param tags_str: A string of the above form to parse tags from.
- :return: A dict containing the tags that were parsed.
- """
- parsed_tags = {}
- if not tags_str:
- return parsed_tags
-
- for tag in tags_str.split(","):
- try:
- key, value = tag.split(":", 1)
-
- # Validate the tag
- if key == "" or value == "" or value.endswith(":"):
- raise ValueError
- except ValueError:
- logger.error(
- "Malformed tag in tag pair '%s' from tag string '%s'.",
- tag,
- tags_str,
- )
- else:
- parsed_tags[key] = value
-
- return parsed_tags
-
-
-def _extract_tags_from_resource(resource):
- """Parse tags from resource.attributes, except service.name which
- has special significance within datadog"""
- tags = {}
- service_name = None
- if not (resource and getattr(resource, "attributes", None)):
- return [tags, service_name]
-
- for attribute_key, attribute_value in resource.attributes.items():
- if attribute_key == SERVICE_NAME_TAG:
- service_name = attribute_value
- else:
- tags[attribute_key] = attribute_value
- return [tags, service_name]
diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/propagator.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/propagator.py
deleted file mode 100644
index ab1468c54ab..00000000000
--- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/propagator.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright The OpenTelemetry 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 typing
-
-from opentelemetry import trace
-from opentelemetry.context import Context
-from opentelemetry.trace import get_current_span, set_span_in_context
-from opentelemetry.trace.propagation.textmap import (
- Getter,
- Setter,
- TextMapPropagator,
- TextMapPropagatorT,
-)
-
-# pylint:disable=relative-beyond-top-level
-from . import constants
-
-
-class DatadogFormat(TextMapPropagator):
- """Propagator for the Datadog HTTP header format.
- """
-
- TRACE_ID_KEY = "x-datadog-trace-id"
- PARENT_ID_KEY = "x-datadog-parent-id"
- SAMPLING_PRIORITY_KEY = "x-datadog-sampling-priority"
- ORIGIN_KEY = "x-datadog-origin"
-
- def extract(
- self,
- getter: Getter[TextMapPropagatorT],
- carrier: TextMapPropagatorT,
- context: typing.Optional[Context] = None,
- ) -> Context:
- trace_id = extract_first_element(
- getter.get(carrier, self.TRACE_ID_KEY)
- )
-
- span_id = extract_first_element(
- getter.get(carrier, self.PARENT_ID_KEY)
- )
-
- sampled = extract_first_element(
- getter.get(carrier, self.SAMPLING_PRIORITY_KEY)
- )
-
- origin = extract_first_element(getter.get(carrier, self.ORIGIN_KEY))
-
- trace_flags = trace.TraceFlags()
- if sampled and int(sampled) in (
- constants.AUTO_KEEP,
- constants.USER_KEEP,
- ):
- trace_flags |= trace.TraceFlags.SAMPLED
-
- if trace_id is None or span_id is None:
- return set_span_in_context(trace.INVALID_SPAN, context)
-
- span_context = trace.SpanContext(
- trace_id=int(trace_id),
- span_id=int(span_id),
- is_remote=True,
- trace_flags=trace_flags,
- trace_state=trace.TraceState({constants.DD_ORIGIN: origin}),
- )
-
- return set_span_in_context(trace.DefaultSpan(span_context), context)
-
- def inject(
- self,
- set_in_carrier: Setter[TextMapPropagatorT],
- carrier: TextMapPropagatorT,
- context: typing.Optional[Context] = None,
- ) -> None:
- span = get_current_span(context)
- span_context = span.get_span_context()
- if span_context == trace.INVALID_SPAN_CONTEXT:
- return
- sampled = (trace.TraceFlags.SAMPLED & span.context.trace_flags) != 0
- set_in_carrier(
- carrier, self.TRACE_ID_KEY, format_trace_id(span.context.trace_id),
- )
- set_in_carrier(
- carrier, self.PARENT_ID_KEY, format_span_id(span.context.span_id)
- )
- set_in_carrier(
- carrier,
- self.SAMPLING_PRIORITY_KEY,
- str(constants.AUTO_KEEP if sampled else constants.AUTO_REJECT),
- )
- if constants.DD_ORIGIN in span.context.trace_state:
- set_in_carrier(
- carrier,
- self.ORIGIN_KEY,
- span.context.trace_state[constants.DD_ORIGIN],
- )
-
-
-def format_trace_id(trace_id: int) -> str:
- """Format the trace id for Datadog."""
- return str(trace_id & 0xFFFFFFFFFFFFFFFF)
-
-
-def format_span_id(span_id: int) -> str:
- """Format the span id for Datadog."""
- return str(span_id)
-
-
-def extract_first_element(
- items: typing.Iterable[TextMapPropagatorT],
-) -> typing.Optional[TextMapPropagatorT]:
- if items is None:
- return None
- return next(iter(items), None)
diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py
deleted file mode 100644
index 3a1188e0bd3..00000000000
--- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py
+++ /dev/null
@@ -1,225 +0,0 @@
-# Copyright The OpenTelemetry 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 collections
-import logging
-import threading
-import typing
-
-from opentelemetry.context import Context, attach, detach, set_value
-from opentelemetry.sdk.trace import Span, SpanProcessor
-from opentelemetry.sdk.trace.export import SpanExporter
-from opentelemetry.trace import INVALID_TRACE_ID
-from opentelemetry.util import time_ns
-
-logger = logging.getLogger(__name__)
-
-
-class DatadogExportSpanProcessor(SpanProcessor):
- """Datadog exporter span processor
-
- DatadogExportSpanProcessor is an implementation of `SpanProcessor` that
- batches all opened spans into a list per trace. When all spans for a trace
- are ended, the trace is queues up for export. This is required for exporting
- to the Datadog Agent which expects to received list of spans for each trace.
- """
-
- _FLUSH_TOKEN = INVALID_TRACE_ID
-
- def __init__(
- self,
- span_exporter: SpanExporter,
- schedule_delay_millis: float = 5000,
- max_trace_size: int = 4096,
- ):
- if max_trace_size <= 0:
- raise ValueError("max_queue_size must be a positive integer.")
-
- if schedule_delay_millis <= 0:
- raise ValueError("schedule_delay_millis must be positive.")
-
- self.span_exporter = span_exporter
-
- # queue trace_ids for traces with recently ended spans for worker thread to check
- # for exporting
- self.check_traces_queue = (
- collections.deque()
- ) # type: typing.Deque[int]
-
- self.traces_lock = threading.Lock()
- # dictionary of trace_ids to a list of spans where the first span is the
- # first opened span for the trace
- self.traces = collections.defaultdict(list)
- # counter to keep track of the number of spans and ended spans for a
- # trace_id
- self.traces_spans_count = collections.Counter()
- self.traces_spans_ended_count = collections.Counter()
-
- self.worker_thread = threading.Thread(target=self.worker, daemon=True)
-
- # threading conditions used for flushing and shutdown
- self.condition = threading.Condition(threading.Lock())
- self.flush_condition = threading.Condition(threading.Lock())
-
- # flag to indicate that there is a flush operation on progress
- self._flushing = False
-
- self.max_trace_size = max_trace_size
- self._spans_dropped = False
- self.schedule_delay_millis = schedule_delay_millis
- self.done = False
- self.worker_thread.start()
-
- def on_start(
- self, span: Span, parent_context: typing.Optional[Context] = None
- ) -> None:
- ctx = span.get_span_context()
- trace_id = ctx.trace_id
-
- with self.traces_lock:
- # check upper bound on number of spans for trace before adding new
- # span
- if self.traces_spans_count[trace_id] == self.max_trace_size:
- logger.warning("Max spans for trace, spans will be dropped.")
- self._spans_dropped = True
- return
-
- # add span to end of list for a trace and update the counter
- self.traces[trace_id].append(span)
- self.traces_spans_count[trace_id] += 1
-
- def on_end(self, span: Span) -> None:
- if self.done:
- logger.warning("Already shutdown, dropping span.")
- return
-
- ctx = span.get_span_context()
- trace_id = ctx.trace_id
-
- with self.traces_lock:
- self.traces_spans_ended_count[trace_id] += 1
- if self.is_trace_exportable(trace_id):
- self.check_traces_queue.appendleft(trace_id)
-
- def worker(self):
- timeout = self.schedule_delay_millis / 1e3
- while not self.done:
- if not self._flushing:
- with self.condition:
- self.condition.wait(timeout)
- if not self.check_traces_queue:
- # spurious notification, let's wait again, reset timeout
- timeout = self.schedule_delay_millis / 1e3
- continue
- if self.done:
- # missing spans will be sent when calling flush
- break
-
- # substract the duration of this export call to the next timeout
- start = time_ns()
- self.export()
- end = time_ns()
- duration = (end - start) / 1e9
- timeout = self.schedule_delay_millis / 1e3 - duration
-
- # be sure that all spans are sent
- self._drain_queue()
-
- def is_trace_exportable(self, trace_id):
- return (
- self.traces_spans_count[trace_id]
- - self.traces_spans_ended_count[trace_id]
- <= 0
- )
-
- def export(self) -> None:
- """Exports traces with finished spans."""
- notify_flush = False
- export_trace_ids = []
-
- while self.check_traces_queue:
- trace_id = self.check_traces_queue.pop()
- if trace_id is self._FLUSH_TOKEN:
- notify_flush = True
- else:
- with self.traces_lock:
- # check whether trace is exportable again in case that new
- # spans were started since we last concluded trace was
- # exportable
- if self.is_trace_exportable(trace_id):
- export_trace_ids.append(trace_id)
- del self.traces_spans_count[trace_id]
- del self.traces_spans_ended_count[trace_id]
-
- if len(export_trace_ids) > 0:
- token = attach(set_value("suppress_instrumentation", True))
-
- for trace_id in export_trace_ids:
- with self.traces_lock:
- try:
- # Ignore type b/c the Optional[None]+slicing is too "clever"
- # for mypy
- self.span_exporter.export(self.traces[trace_id]) # type: ignore
- # pylint: disable=broad-except
- except Exception:
- logger.exception(
- "Exception while exporting Span batch."
- )
- finally:
- del self.traces[trace_id]
-
- detach(token)
-
- if notify_flush:
- with self.flush_condition:
- self.flush_condition.notify()
-
- def _drain_queue(self):
- """"Export all elements until queue is empty.
-
- Can only be called from the worker thread context because it invokes
- `export` that is not thread safe.
- """
- while self.check_traces_queue:
- self.export()
-
- def force_flush(self, timeout_millis: int = 30000) -> bool:
- if self.done:
- logger.warning("Already shutdown, ignoring call to force_flush().")
- return True
-
- self._flushing = True
- self.check_traces_queue.appendleft(self._FLUSH_TOKEN)
-
- # wake up worker thread
- with self.condition:
- self.condition.notify_all()
-
- # wait for token to be processed
- with self.flush_condition:
- ret = self.flush_condition.wait(timeout_millis / 1e3)
-
- self._flushing = False
-
- if not ret:
- logger.warning("Timeout was exceeded in force_flush().")
- return ret
-
- def shutdown(self) -> None:
- # signal the worker thread to finish and then wait for it
- self.done = True
- with self.condition:
- self.condition.notify_all()
- self.worker_thread.join()
- self.span_exporter.shutdown()
diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/version.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/exporter/opentelemetry-exporter-datadog/tests/__init__.py b/exporter/opentelemetry-exporter-datadog/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py
deleted file mode 100644
index 7b94704a573..00000000000
--- a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py
+++ /dev/null
@@ -1,604 +0,0 @@
-# Copyright The OpenTelemetry 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 itertools
-import logging
-import time
-import unittest
-from unittest import mock
-
-from ddtrace.internal.writer import AgentWriter
-
-from opentelemetry import trace as trace_api
-from opentelemetry.context import Context
-from opentelemetry.exporter import datadog
-from opentelemetry.sdk import trace
-from opentelemetry.sdk.trace import Resource, sampling
-from opentelemetry.sdk.util.instrumentation import InstrumentationInfo
-
-
-class MockDatadogSpanExporter(datadog.DatadogSpanExporter):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- agent_writer_mock = mock.Mock(spec=AgentWriter)
- agent_writer_mock.started = True
- agent_writer_mock.exit_timeout = 1
- self._agent_writer = agent_writer_mock
-
-
-def get_spans(tracer, exporter, shutdown=True):
- if shutdown:
- tracer.span_processor.shutdown()
-
- spans = [
- call_args[-1]["spans"]
- for call_args in exporter.agent_writer.write.call_args_list
- ]
-
- return [span.to_dict() for span in itertools.chain.from_iterable(spans)]
-
-
-class TestDatadogSpanExporter(unittest.TestCase):
- def setUp(self):
- self.exporter = MockDatadogSpanExporter()
- self.span_processor = datadog.DatadogExportSpanProcessor(self.exporter)
- tracer_provider = trace.TracerProvider()
- tracer_provider.add_span_processor(self.span_processor)
- self.tracer_provider = tracer_provider
- self.tracer = tracer_provider.get_tracer(__name__)
-
- def tearDown(self):
- self.tracer_provider.shutdown()
-
- def test_constructor_default(self):
- """Test the default values assigned by constructor."""
- exporter = datadog.DatadogSpanExporter()
-
- self.assertEqual(exporter.agent_url, "http://localhost:8126")
- self.assertIsNone(exporter.service)
- self.assertIsNotNone(exporter.agent_writer)
-
- def test_constructor_explicit(self):
- """Test the constructor passing all the options."""
- agent_url = "http://localhost:8126"
- exporter = datadog.DatadogSpanExporter(
- agent_url=agent_url, service="explicit",
- )
-
- self.assertEqual(exporter.agent_url, agent_url)
- self.assertEqual(exporter.service, "explicit")
- self.assertIsNone(exporter.env)
- self.assertIsNone(exporter.version)
- self.assertEqual(exporter.tags, {})
-
- exporter = datadog.DatadogSpanExporter(
- agent_url=agent_url,
- service="explicit",
- env="test",
- version="0.0.1",
- tags="",
- )
-
- self.assertEqual(exporter.agent_url, agent_url)
- self.assertEqual(exporter.service, "explicit")
- self.assertEqual(exporter.env, "test")
- self.assertEqual(exporter.version, "0.0.1")
- self.assertEqual(exporter.tags, {})
-
- exporter = datadog.DatadogSpanExporter(
- agent_url=agent_url,
- service="explicit",
- env="test",
- version="0.0.1",
- tags="team:testers,layer:app",
- )
-
- self.assertEqual(exporter.agent_url, agent_url)
- self.assertEqual(exporter.service, "explicit")
- self.assertEqual(exporter.env, "test")
- self.assertEqual(exporter.version, "0.0.1")
- self.assertEqual(exporter.tags, {"team": "testers", "layer": "app"})
-
- @mock.patch.dict(
- "os.environ",
- {
- "DD_TRACE_AGENT_URL": "http://agent:8126",
- "DD_SERVICE": "test-service",
- "DD_ENV": "test",
- "DD_VERSION": "0.0.1",
- "DD_TAGS": "team:testers",
- },
- )
- def test_constructor_environ(self):
- exporter = datadog.DatadogSpanExporter()
-
- self.assertEqual(exporter.agent_url, "http://agent:8126")
- self.assertEqual(exporter.service, "test-service")
- self.assertEqual(exporter.env, "test")
- self.assertEqual(exporter.version, "0.0.1")
- self.assertEqual(exporter.tags, {"team": "testers"})
- self.assertIsNotNone(exporter.agent_writer)
-
- # pylint: disable=too-many-locals
- @mock.patch.dict(
- "os.environ",
- {
- "DD_SERVICE": "test-service",
- "DD_ENV": "test",
- "DD_VERSION": "0.0.1",
- "DD_TAGS": "team:testers",
- },
- )
- def test_translate_to_datadog(self):
- # pylint: disable=invalid-name
- self.maxDiff = None
-
- resource = Resource(
- attributes={
- "key_resource": "some_resource",
- "service.name": "resource_service_name",
- }
- )
-
- resource_without_service = Resource(
- attributes={"conflicting_key": "conflicting_value"}
- )
-
- span_names = ("test1", "test2", "test3")
- trace_id = 0x6E0C63257DE34C926F9EFCD03927272E
- trace_id_low = 0x6F9EFCD03927272E
- span_id = 0x34BF92DEEFC58C92
- parent_id = 0x1111111111111111
- other_id = 0x2222222222222222
-
- base_time = 683647322 * 10 ** 9 # in ns
- start_times = (
- base_time,
- base_time + 150 * 10 ** 6,
- base_time + 300 * 10 ** 6,
- )
- durations = (50 * 10 ** 6, 100 * 10 ** 6, 200 * 10 ** 6)
- end_times = (
- start_times[0] + durations[0],
- start_times[1] + durations[1],
- start_times[2] + durations[2],
- )
-
- span_context = trace_api.SpanContext(
- trace_id, span_id, is_remote=False
- )
- parent_span_context = trace_api.SpanContext(
- trace_id, parent_id, is_remote=False
- )
- other_context = trace_api.SpanContext(
- trace_id, other_id, is_remote=False
- )
-
- instrumentation_info = InstrumentationInfo(__name__, "0")
-
- otel_spans = [
- trace._Span(
- name=span_names[0],
- context=span_context,
- parent=parent_span_context,
- kind=trace_api.SpanKind.CLIENT,
- instrumentation_info=instrumentation_info,
- resource=Resource({}),
- ),
- trace._Span(
- name=span_names[1],
- context=parent_span_context,
- parent=None,
- instrumentation_info=instrumentation_info,
- resource=resource_without_service,
- ),
- trace._Span(
- name=span_names[2],
- context=other_context,
- parent=None,
- resource=resource,
- ),
- ]
-
- otel_spans[1].set_attribute("conflicting_key", "original_value")
-
- otel_spans[0].start(start_time=start_times[0])
- otel_spans[0].end(end_time=end_times[0])
-
- otel_spans[1].start(start_time=start_times[1])
- otel_spans[1].end(end_time=end_times[1])
-
- otel_spans[2].start(start_time=start_times[2])
- otel_spans[2].end(end_time=end_times[2])
-
- # pylint: disable=protected-access
- exporter = datadog.DatadogSpanExporter()
- datadog_spans = [
- span.to_dict()
- for span in exporter._translate_to_datadog(otel_spans)
- ]
-
- expected_spans = [
- dict(
- trace_id=trace_id_low,
- parent_id=parent_id,
- span_id=span_id,
- name="tests.test_datadog_exporter.CLIENT",
- resource=span_names[0],
- start=start_times[0],
- duration=durations[0],
- error=0,
- service="test-service",
- meta={"env": "test", "team": "testers"},
- ),
- dict(
- trace_id=trace_id_low,
- parent_id=0,
- span_id=parent_id,
- name="tests.test_datadog_exporter.INTERNAL",
- resource=span_names[1],
- start=start_times[1],
- duration=durations[1],
- error=0,
- service="test-service",
- meta={
- "env": "test",
- "team": "testers",
- "version": "0.0.1",
- "conflicting_key": "original_value",
- },
- ),
- dict(
- trace_id=trace_id_low,
- parent_id=0,
- span_id=other_id,
- name=span_names[2],
- resource=span_names[2],
- start=start_times[2],
- duration=durations[2],
- error=0,
- service="resource_service_name",
- meta={
- "env": "test",
- "team": "testers",
- "version": "0.0.1",
- "key_resource": "some_resource",
- },
- ),
- ]
-
- self.assertEqual(datadog_spans, expected_spans)
-
- def test_export(self):
- """Test that agent and/or collector are invoked"""
- # create and save span to be used in tests
- context = trace_api.SpanContext(
- trace_id=0x000000000000000000000000DEADBEEF,
- span_id=0x00000000DEADBEF0,
- is_remote=False,
- )
-
- test_span = trace._Span("test_span", context=context)
- test_span.start()
- test_span.end()
-
- self.exporter.export((test_span,))
-
- self.assertEqual(self.exporter.agent_writer.write.call_count, 1)
-
- def test_resources(self):
- test_attributes = [
- {},
- {"http.method": "GET", "http.route": "/foo/"},
- {"http.method": "GET", "http.target": "/foo/200"},
- ]
-
- for index, test in enumerate(test_attributes):
- with self.tracer.start_span(str(index), attributes=test):
- pass
-
- datadog_spans = get_spans(self.tracer, self.exporter)
-
- self.assertEqual(len(datadog_spans), 3)
-
- actual = [span["resource"] for span in datadog_spans]
- expected = ["0", "GET /foo/", "GET"]
-
- self.assertEqual(actual, expected)
-
- def test_span_types(self):
- test_instrumentations = [
- "opentelemetry.instrumentation.aiohttp-client",
- "opentelemetry.instrumentation.dbapi",
- "opentelemetry.instrumentation.django",
- "opentelemetry.instrumentation.flask",
- "opentelemetry.instrumentation.grpc",
- "opentelemetry.instrumentation.jinja2",
- "opentelemetry.instrumentation.mysql",
- "opentelemetry.instrumentation.psycopg2",
- "opentelemetry.instrumentation.pymongo",
- "opentelemetry.instrumentation.pymysql",
- "opentelemetry.instrumentation.redis",
- "opentelemetry.instrumentation.requests",
- "opentelemetry.instrumentation.sqlalchemy",
- "opentelemetry.instrumentation.wsgi",
- ]
-
- for index, instrumentation in enumerate(test_instrumentations):
- # change tracer's instrumentation info before starting span
- self.tracer.instrumentation_info = InstrumentationInfo(
- instrumentation, "0"
- )
- with self.tracer.start_span(str(index)):
- pass
-
- datadog_spans = get_spans(self.tracer, self.exporter)
-
- self.assertEqual(len(datadog_spans), 14)
-
- actual = [span.get("type") for span in datadog_spans]
- expected = [
- "http",
- "sql",
- "web",
- "web",
- "grpc",
- "template",
- "sql",
- "sql",
- "mongodb",
- "sql",
- "redis",
- "http",
- "sql",
- "web",
- ]
- self.assertEqual(actual, expected)
-
- def test_errors(self):
- with self.assertRaises(ValueError):
- with self.tracer.start_span("foo"):
- raise ValueError("bar")
-
- datadog_spans = get_spans(self.tracer, self.exporter)
-
- self.assertEqual(len(datadog_spans), 1)
-
- span = datadog_spans[0]
- self.assertEqual(span["error"], 1)
- self.assertEqual(span["meta"]["error.msg"], "bar")
- self.assertEqual(span["meta"]["error.type"], "ValueError")
-
- def test_shutdown(self):
- span_names = ["xxx", "bar", "foo"]
-
- for name in span_names:
- with self.tracer.start_span(name):
- pass
-
- self.span_processor.shutdown()
-
- # check that spans are exported without an explicitly call to
- # force_flush()
- datadog_spans = get_spans(self.tracer, self.exporter)
- actual = [span.get("resource") for span in datadog_spans]
- self.assertListEqual(span_names, actual)
-
- def test_flush(self):
- span_names0 = ["xxx", "bar", "foo"]
- span_names1 = ["yyy", "baz", "fox"]
-
- for name in span_names0:
- with self.tracer.start_span(name):
- pass
-
- self.assertTrue(self.span_processor.force_flush())
- datadog_spans = get_spans(self.tracer, self.exporter, shutdown=False)
- actual0 = [span.get("resource") for span in datadog_spans]
- self.assertListEqual(span_names0, actual0)
-
- # create some more spans to check that span processor still works
- for name in span_names1:
- with self.tracer.start_span(name):
- pass
-
- self.assertTrue(self.span_processor.force_flush())
- datadog_spans = get_spans(self.tracer, self.exporter)
- actual1 = [span.get("resource") for span in datadog_spans]
- self.assertListEqual(span_names0 + span_names1, actual1)
-
- def test_span_processor_lossless(self):
- """Test that no spans are lost when sending max_trace_size spans"""
- span_processor = datadog.DatadogExportSpanProcessor(
- self.exporter, max_trace_size=128
- )
- tracer_provider = trace.TracerProvider()
- tracer_provider.add_span_processor(span_processor)
- tracer = tracer_provider.get_tracer(__name__)
-
- with tracer.start_as_current_span("root"):
- for _ in range(127):
- with tracer.start_span("foo"):
- pass
-
- self.assertTrue(span_processor.force_flush())
- datadog_spans = get_spans(tracer, self.exporter)
- self.assertEqual(len(datadog_spans), 128)
- tracer_provider.shutdown()
-
- def test_span_processor_dropped_spans(self):
- """Test that spans are lost when exceeding max_trace_size spans"""
- span_processor = datadog.DatadogExportSpanProcessor(
- self.exporter, max_trace_size=128
- )
- tracer_provider = trace.TracerProvider()
- tracer_provider.add_span_processor(span_processor)
- tracer = tracer_provider.get_tracer(__name__)
-
- with tracer.start_as_current_span("root"):
- for _ in range(127):
- with tracer.start_span("foo"):
- pass
- with self.assertLogs(level=logging.WARNING):
- with tracer.start_span("one-too-many"):
- pass
-
- self.assertTrue(span_processor.force_flush())
- datadog_spans = get_spans(tracer, self.exporter)
- self.assertEqual(len(datadog_spans), 128)
- tracer_provider.shutdown()
-
- def test_span_processor_scheduled_delay(self):
- """Test that spans are exported each schedule_delay_millis"""
- delay = 300
- span_processor = datadog.DatadogExportSpanProcessor(
- self.exporter, schedule_delay_millis=delay
- )
- tracer_provider = trace.TracerProvider()
- tracer_provider.add_span_processor(span_processor)
- tracer = tracer_provider.get_tracer(__name__)
-
- with tracer.start_span("foo"):
- pass
-
- time.sleep(delay / (1e3 * 2))
- datadog_spans = get_spans(tracer, self.exporter, shutdown=False)
- self.assertEqual(len(datadog_spans), 0)
-
- time.sleep(delay / (1e3 * 2) + 0.01)
- datadog_spans = get_spans(tracer, self.exporter, shutdown=False)
- self.assertEqual(len(datadog_spans), 1)
-
- tracer_provider.shutdown()
-
- def test_batch_span_processor_reset_timeout(self):
- """Test that the scheduled timeout is reset on cycles without spans"""
- delay = 50
- # pylint: disable=protected-access
- exporter = MockDatadogSpanExporter()
- exporter._agent_writer.write.side_effect = lambda spans: time.sleep(
- 0.05
- )
- span_processor = datadog.DatadogExportSpanProcessor(
- exporter, schedule_delay_millis=delay
- )
- tracer_provider = trace.TracerProvider()
- tracer_provider.add_span_processor(span_processor)
- tracer = tracer_provider.get_tracer(__name__)
- with mock.patch.object(span_processor.condition, "wait") as mock_wait:
- with tracer.start_span("foo"):
- pass
-
- # give some time for exporter to loop
- # since wait is mocked it should return immediately
- time.sleep(0.1)
- mock_wait_calls = list(mock_wait.mock_calls)
-
- # find the index of the call that processed the singular span
- for idx, wait_call in enumerate(mock_wait_calls):
- _, args, __ = wait_call
- if args[0] <= 0:
- after_calls = mock_wait_calls[idx + 1 :]
- break
-
- self.assertTrue(
- all(args[0] >= 0.05 for _, args, __ in after_calls)
- )
-
- span_processor.shutdown()
-
- def test_span_processor_accepts_parent_context(self):
- span_processor = mock.Mock(
- wraps=datadog.DatadogExportSpanProcessor(self.exporter)
- )
- tracer_provider = trace.TracerProvider()
- tracer_provider.add_span_processor(span_processor)
- tracer = tracer_provider.get_tracer(__name__)
-
- context = Context()
- span = tracer.start_span("foo", context=context)
-
- span_processor.on_start.assert_called_once_with(
- span, parent_context=context
- )
-
- def test_origin(self):
- context = trace_api.SpanContext(
- trace_id=0x000000000000000000000000DEADBEEF,
- span_id=trace_api.INVALID_SPAN,
- is_remote=True,
- trace_state=trace_api.TraceState(
- {datadog.constants.DD_ORIGIN: "origin-service"}
- ),
- )
-
- root_span = trace._Span(name="root", context=context, parent=None)
- child_span = trace._Span(
- name="child", context=context, parent=root_span
- )
- root_span.start()
- child_span.start()
- child_span.end()
- root_span.end()
-
- # pylint: disable=protected-access
- exporter = datadog.DatadogSpanExporter()
- datadog_spans = [
- span.to_dict()
- for span in exporter._translate_to_datadog([root_span, child_span])
- ]
-
- self.assertEqual(len(datadog_spans), 2)
-
- actual = [
- span["meta"].get(datadog.constants.DD_ORIGIN)
- if "meta" in span
- else None
- for span in datadog_spans
- ]
- expected = ["origin-service", None]
- self.assertListEqual(actual, expected)
-
- def test_sampling_rate(self):
- context = trace_api.SpanContext(
- trace_id=0x000000000000000000000000DEADBEEF,
- span_id=0x34BF92DEEFC58C92,
- is_remote=False,
- trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED),
- )
- sampler = sampling.TraceIdRatioBased(0.5)
-
- span = trace._Span(
- name="sampled", context=context, parent=None, sampler=sampler
- )
- span.start()
- span.end()
-
- # pylint: disable=protected-access
- exporter = datadog.DatadogSpanExporter()
- datadog_spans = [
- span.to_dict() for span in exporter._translate_to_datadog([span])
- ]
-
- self.assertEqual(len(datadog_spans), 1)
-
- actual = [
- span["metrics"].get(datadog.constants.SAMPLE_RATE_METRIC_KEY)
- if "metrics" in span
- else None
- for span in datadog_spans
- ]
- expected = [0.5]
- self.assertListEqual(actual, expected)
diff --git a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_format.py b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_format.py
deleted file mode 100644
index bb41fef49b1..00000000000
--- a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_format.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest
-
-from opentelemetry import trace as trace_api
-from opentelemetry.exporter.datadog import constants, propagator
-from opentelemetry.sdk import trace
-from opentelemetry.trace import get_current_span, set_span_in_context
-from opentelemetry.trace.propagation.textmap import DictGetter
-
-FORMAT = propagator.DatadogFormat()
-
-carrier_getter = DictGetter()
-
-
-class TestDatadogFormat(unittest.TestCase):
- @classmethod
- def setUpClass(cls):
- ids_generator = trace_api.RandomIdsGenerator()
- cls.serialized_trace_id = propagator.format_trace_id(
- ids_generator.generate_trace_id()
- )
- cls.serialized_parent_id = propagator.format_span_id(
- ids_generator.generate_span_id()
- )
- cls.serialized_origin = "origin-service"
-
- def test_malformed_headers(self):
- """Test with no Datadog headers"""
- malformed_trace_id_key = FORMAT.TRACE_ID_KEY + "-x"
- malformed_parent_id_key = FORMAT.PARENT_ID_KEY + "-x"
- context = get_current_span(
- FORMAT.extract(
- carrier_getter,
- {
- malformed_trace_id_key: self.serialized_trace_id,
- malformed_parent_id_key: self.serialized_parent_id,
- },
- )
- ).get_span_context()
-
- self.assertNotEqual(context.trace_id, int(self.serialized_trace_id))
- self.assertNotEqual(context.span_id, int(self.serialized_parent_id))
- self.assertFalse(context.is_remote)
-
- def test_missing_trace_id(self):
- """If a trace id is missing, populate an invalid trace id."""
- carrier = {
- FORMAT.PARENT_ID_KEY: self.serialized_parent_id,
- }
-
- ctx = FORMAT.extract(carrier_getter, carrier)
- span_context = get_current_span(ctx).get_span_context()
- self.assertEqual(span_context.trace_id, trace_api.INVALID_TRACE_ID)
-
- def test_missing_parent_id(self):
- """If a parent id is missing, populate an invalid trace id."""
- carrier = {
- FORMAT.TRACE_ID_KEY: self.serialized_trace_id,
- }
-
- ctx = FORMAT.extract(carrier_getter, carrier)
- span_context = get_current_span(ctx).get_span_context()
- self.assertEqual(span_context.span_id, trace_api.INVALID_SPAN_ID)
-
- def test_context_propagation(self):
- """Test the propagation of Datadog headers."""
- parent_span_context = get_current_span(
- FORMAT.extract(
- carrier_getter,
- {
- FORMAT.TRACE_ID_KEY: self.serialized_trace_id,
- FORMAT.PARENT_ID_KEY: self.serialized_parent_id,
- FORMAT.SAMPLING_PRIORITY_KEY: str(constants.AUTO_KEEP),
- FORMAT.ORIGIN_KEY: self.serialized_origin,
- },
- )
- ).get_span_context()
-
- self.assertEqual(
- parent_span_context.trace_id, int(self.serialized_trace_id)
- )
- self.assertEqual(
- parent_span_context.span_id, int(self.serialized_parent_id)
- )
- self.assertEqual(parent_span_context.trace_flags, constants.AUTO_KEEP)
- self.assertEqual(
- parent_span_context.trace_state.get(constants.DD_ORIGIN),
- self.serialized_origin,
- )
- self.assertTrue(parent_span_context.is_remote)
-
- child = trace._Span(
- "child",
- trace_api.SpanContext(
- parent_span_context.trace_id,
- trace_api.RandomIdsGenerator().generate_span_id(),
- is_remote=False,
- trace_flags=parent_span_context.trace_flags,
- trace_state=parent_span_context.trace_state,
- ),
- parent=parent_span_context,
- )
-
- child_carrier = {}
- child_context = set_span_in_context(child)
- FORMAT.inject(dict.__setitem__, child_carrier, context=child_context)
-
- self.assertEqual(
- child_carrier[FORMAT.TRACE_ID_KEY], self.serialized_trace_id
- )
- self.assertEqual(
- child_carrier[FORMAT.PARENT_ID_KEY], str(child.context.span_id)
- )
- self.assertEqual(
- child_carrier[FORMAT.SAMPLING_PRIORITY_KEY],
- str(constants.AUTO_KEEP),
- )
- self.assertEqual(
- child_carrier.get(FORMAT.ORIGIN_KEY), self.serialized_origin
- )
-
- def test_sampling_priority_auto_reject(self):
- """Test sampling priority rejected."""
- parent_span_context = get_current_span(
- FORMAT.extract(
- carrier_getter,
- {
- FORMAT.TRACE_ID_KEY: self.serialized_trace_id,
- FORMAT.PARENT_ID_KEY: self.serialized_parent_id,
- FORMAT.SAMPLING_PRIORITY_KEY: str(constants.AUTO_REJECT),
- },
- )
- ).get_span_context()
-
- self.assertEqual(
- parent_span_context.trace_flags, constants.AUTO_REJECT
- )
-
- child = trace._Span(
- "child",
- trace_api.SpanContext(
- parent_span_context.trace_id,
- trace_api.RandomIdsGenerator().generate_span_id(),
- is_remote=False,
- trace_flags=parent_span_context.trace_flags,
- trace_state=parent_span_context.trace_state,
- ),
- parent=parent_span_context,
- )
-
- child_carrier = {}
- child_context = set_span_in_context(child)
- FORMAT.inject(dict.__setitem__, child_carrier, context=child_context)
-
- self.assertEqual(
- child_carrier[FORMAT.SAMPLING_PRIORITY_KEY],
- str(constants.AUTO_REJECT),
- )
diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-aiohttp-client/CHANGELOG.md
deleted file mode 100644
index 8b1d3ee2c1b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/CHANGELOG.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Updating span name to match semantic conventions
- ([#972](https://github.com/open-telemetry/opentelemetry-python/pull/972))
-- Add instrumentor and auto instrumentation support for aiohttp
- ([#1075](https://github.com/open-telemetry/opentelemetry-python/pull/1075))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-aiohttp-client
- ([#961](https://github.com/open-telemetry/opentelemetry-python/pull/961))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/LICENSE b/instrumentation/opentelemetry-instrumentation-aiohttp-client/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-aiohttp-client/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-aiohttp-client/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/README.rst b/instrumentation/opentelemetry-instrumentation-aiohttp-client/README.rst
deleted file mode 100644
index bc44e0e2627..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/README.rst
+++ /dev/null
@@ -1,24 +0,0 @@
-OpenTelemetry aiohttp client Integration
-========================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-aiohttp-client.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-aiohttp-client/
-
-This library allows tracing HTTP requests made by the
-`aiohttp client `_ library.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-aiohttp-client
-
-
-References
-----------
-
-* `OpenTelemetry Project `_
-* `aiohttp client Tracing `_
diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.cfg b/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.cfg
deleted file mode 100644
index e0fcfbf4b0c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.cfg
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2020, OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-aiohttp-client
-description = OpenTelemetry aiohttp client instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/instrumentation/opentelemetry-instrumentation-aiohttp-client
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5.3
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- aiohttp ~= 3.0
- wrapt >= 1.0.0, < 2.0.0
-
-[options.packages.find]
-where = src
-
-[options.extras_require]
-test =
-
-[options.entry_points]
-opentelemetry_instrumentor =
- aiohttp-client = opentelemetry.instrumentation.aiohttp_client:AioHttpClientInstrumentor
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.py
deleted file mode 100644
index fe74e232353..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2020, OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "aiohttp_client",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py
deleted file mode 100644
index c708802a926..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py
+++ /dev/null
@@ -1,315 +0,0 @@
-# Copyright 2020, OpenTelemetry 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.
-
-"""
-The opentelemetry-instrumentation-aiohttp-client package allows tracing HTTP
-requests made by the aiohttp client library.
-
-Usage
------
-Explicitly instrumenting a single client session:
-
-.. code:: python
-
- import aiohttp
- from opentelemetry.instrumentation.aiohttp_client import (
- create_trace_config,
- url_path_span_name
- )
- import yarl
-
- def strip_query_params(url: yarl.URL) -> str:
- return str(url.with_query(None))
-
- async with aiohttp.ClientSession(trace_configs=[create_trace_config(
- # Remove all query params from the URL attribute on the span.
- url_filter=strip_query_params,
- # Use the URL's path as the span name.
- span_name=url_path_span_name
- )]) as session:
- async with session.get(url) as response:
- await response.text()
-
-Instrumenting all client sessions:
-
-.. code:: python
-
- import aiohttp
- from opentelemetry.instrumentation.aiohttp_client import (
- AioHttpClientInstrumentor
- )
-
- # Enable instrumentation
- AioHttpClientInstrumentor().instrument()
-
- # Create a session and make an HTTP get request
- async with aiohttp.ClientSession() as session:
- async with session.get(url) as response:
- await response.text()
-
-API
----
-"""
-
-import socket
-import types
-import typing
-
-import aiohttp
-import wrapt
-
-from opentelemetry import context as context_api
-from opentelemetry import propagators, trace
-from opentelemetry.instrumentation.aiohttp_client.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.utils import (
- http_status_to_status_code,
- unwrap,
-)
-from opentelemetry.trace import SpanKind, TracerProvider, get_tracer
-from opentelemetry.trace.status import Status, StatusCode
-
-_UrlFilterT = typing.Optional[typing.Callable[[str], str]]
-_SpanNameT = typing.Optional[
- typing.Union[typing.Callable[[aiohttp.TraceRequestStartParams], str], str]
-]
-
-
-def url_path_span_name(params: aiohttp.TraceRequestStartParams) -> str:
- """Extract a span name from the request URL path.
-
- A simple callable to extract the path portion of the requested URL
- for use as the span name.
-
- :param aiohttp.TraceRequestStartParams params: Parameters describing
- the traced request.
-
- :return: The URL path.
- :rtype: str
- """
- return params.url.path
-
-
-def create_trace_config(
- url_filter: _UrlFilterT = None,
- span_name: _SpanNameT = None,
- tracer_provider: TracerProvider = None,
-) -> aiohttp.TraceConfig:
- """Create an aiohttp-compatible trace configuration.
-
- One span is created for the entire HTTP request, including initial
- TCP/TLS setup if the connection doesn't exist.
-
- By default the span name is set to the HTTP request method.
-
- Example usage:
-
- .. code:: python
-
- import aiohttp
- from opentelemetry.instrumentation.aiohttp_client import create_trace_config
-
- async with aiohttp.ClientSession(trace_configs=[create_trace_config()]) as session:
- async with session.get(url) as response:
- await response.text()
-
-
- :param url_filter: A callback to process the requested URL prior to adding
- it as a span attribute. This can be useful to remove sensitive data
- such as API keys or user personal information.
-
- :param str span_name: Override the default span name.
- :param tracer_provider: optional TracerProvider from which to get a Tracer
-
- :return: An object suitable for use with :py:class:`aiohttp.ClientSession`.
- :rtype: :py:class:`aiohttp.TraceConfig`
- """
- # `aiohttp.TraceRequestStartParams` resolves to `aiohttp.tracing.TraceRequestStartParams`
- # which doesn't exist in the aiottp intersphinx inventory.
- # Explicitly specify the type for the `span_name` param and rtype to work
- # around this issue.
-
- tracer = get_tracer(__name__, __version__, tracer_provider)
-
- def _end_trace(trace_config_ctx: types.SimpleNamespace):
- context_api.detach(trace_config_ctx.token)
- trace_config_ctx.span.end()
-
- async def on_request_start(
- unused_session: aiohttp.ClientSession,
- trace_config_ctx: types.SimpleNamespace,
- params: aiohttp.TraceRequestStartParams,
- ):
- if context_api.get_value("suppress_instrumentation"):
- trace_config_ctx.span = None
- return
-
- http_method = params.method.upper()
- if trace_config_ctx.span_name is None:
- request_span_name = "HTTP {}".format(http_method)
- elif callable(trace_config_ctx.span_name):
- request_span_name = str(trace_config_ctx.span_name(params))
- else:
- request_span_name = str(trace_config_ctx.span_name)
-
- trace_config_ctx.span = trace_config_ctx.tracer.start_span(
- request_span_name, kind=SpanKind.CLIENT,
- )
-
- if trace_config_ctx.span.is_recording():
- attributes = {
- "component": "http",
- "http.method": http_method,
- "http.url": trace_config_ctx.url_filter(params.url)
- if callable(trace_config_ctx.url_filter)
- else str(params.url),
- }
- for key, value in attributes.items():
- trace_config_ctx.span.set_attribute(key, value)
-
- trace_config_ctx.token = context_api.attach(
- trace.set_span_in_context(trace_config_ctx.span)
- )
-
- propagators.inject(type(params.headers).__setitem__, params.headers)
-
- async def on_request_end(
- unused_session: aiohttp.ClientSession,
- trace_config_ctx: types.SimpleNamespace,
- params: aiohttp.TraceRequestEndParams,
- ):
- if trace_config_ctx.span is None:
- return
-
- if trace_config_ctx.span.is_recording():
- trace_config_ctx.span.set_status(
- Status(http_status_to_status_code(int(params.response.status)))
- )
- trace_config_ctx.span.set_attribute(
- "http.status_code", params.response.status
- )
- trace_config_ctx.span.set_attribute(
- "http.status_text", params.response.reason
- )
- _end_trace(trace_config_ctx)
-
- async def on_request_exception(
- unused_session: aiohttp.ClientSession,
- trace_config_ctx: types.SimpleNamespace,
- params: aiohttp.TraceRequestExceptionParams,
- ):
- if trace_config_ctx.span is None:
- return
-
- if trace_config_ctx.span.is_recording() and params.exception:
- trace_config_ctx.span.set_status(Status(StatusCode.ERROR))
- trace_config_ctx.span.record_exception(params.exception)
- _end_trace(trace_config_ctx)
-
- def _trace_config_ctx_factory(**kwargs):
- kwargs.setdefault("trace_request_ctx", {})
- return types.SimpleNamespace(
- span_name=span_name, tracer=tracer, url_filter=url_filter, **kwargs
- )
-
- trace_config = aiohttp.TraceConfig(
- trace_config_ctx_factory=_trace_config_ctx_factory
- )
-
- trace_config.on_request_start.append(on_request_start)
- trace_config.on_request_end.append(on_request_end)
- trace_config.on_request_exception.append(on_request_exception)
-
- return trace_config
-
-
-def _instrument(
- tracer_provider: TracerProvider = None,
- url_filter: _UrlFilterT = None,
- span_name: _SpanNameT = None,
-):
- """Enables tracing of all ClientSessions
-
- When a ClientSession gets created a TraceConfig is automatically added to
- the session's trace_configs.
- """
- # pylint:disable=unused-argument
- def instrumented_init(wrapped, instance, args, kwargs):
- if context_api.get_value("suppress_instrumentation"):
- return wrapped(*args, **kwargs)
-
- trace_configs = list(kwargs.get("trace_configs") or ())
-
- trace_config = create_trace_config(
- url_filter=url_filter,
- span_name=span_name,
- tracer_provider=tracer_provider,
- )
- trace_config.opentelemetry_aiohttp_instrumented = True
- trace_configs.append(trace_config)
-
- kwargs["trace_configs"] = trace_configs
- return wrapped(*args, **kwargs)
-
- wrapt.wrap_function_wrapper(
- aiohttp.ClientSession, "__init__", instrumented_init
- )
-
-
-def _uninstrument():
- """Disables instrumenting for all newly created ClientSessions"""
- unwrap(aiohttp.ClientSession, "__init__")
-
-
-def _uninstrument_session(client_session: aiohttp.ClientSession):
- """Disables instrumentation for the given ClientSession"""
- # pylint: disable=protected-access
- trace_configs = client_session._trace_configs
- client_session._trace_configs = [
- trace_config
- for trace_config in trace_configs
- if not hasattr(trace_config, "opentelemetry_aiohttp_instrumented")
- ]
-
-
-class AioHttpClientInstrumentor(BaseInstrumentor):
- """An instrumentor for aiohttp client sessions
-
- See `BaseInstrumentor`
- """
-
- def _instrument(self, **kwargs):
- """Instruments aiohttp ClientSession
-
- Args:
- **kwargs: Optional arguments
- ``tracer_provider``: a TracerProvider, defaults to global
- ``url_filter``: A callback to process the requested URL prior to adding
- it as a span attribute. This can be useful to remove sensitive data
- such as API keys or user personal information.
- ``span_name``: Override the default span name.
- """
- _instrument(
- tracer_provider=kwargs.get("tracer_provider"),
- url_filter=kwargs.get("url_filter"),
- span_name=kwargs.get("span_name"),
- )
-
- def _uninstrument(self, **kwargs):
- _uninstrument()
-
- @staticmethod
- def uninstrument_session(client_session: aiohttp.ClientSession):
- """Disables instrumentation for the given session"""
- _uninstrument_session(client_session)
diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/version.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/version.py
deleted file mode 100644
index bb32120c79b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2020, OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py
deleted file mode 100644
index f0734653488..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py
+++ /dev/null
@@ -1,500 +0,0 @@
-# Copyright 2020, OpenTelemetry 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 asyncio
-import contextlib
-import typing
-import unittest
-import urllib.parse
-from http import HTTPStatus
-from unittest import mock
-
-import aiohttp
-import aiohttp.test_utils
-import yarl
-from pkg_resources import iter_entry_points
-
-from opentelemetry import context
-from opentelemetry.instrumentation import aiohttp_client
-from opentelemetry.instrumentation.aiohttp_client import (
- AioHttpClientInstrumentor,
-)
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace.status import StatusCode
-
-
-def run_with_test_server(
- runnable: typing.Callable, url: str, handler: typing.Callable
-) -> typing.Tuple[str, int]:
- async def do_request():
- app = aiohttp.web.Application()
- parsed_url = urllib.parse.urlparse(url)
- app.add_routes([aiohttp.web.get(parsed_url.path, handler)])
- app.add_routes([aiohttp.web.post(parsed_url.path, handler)])
- app.add_routes([aiohttp.web.patch(parsed_url.path, handler)])
-
- with contextlib.suppress(aiohttp.ClientError):
- async with aiohttp.test_utils.TestServer(app) as server:
- netloc = (server.host, server.port)
- await server.start_server()
- await runnable(server)
- return netloc
-
- loop = asyncio.get_event_loop()
- return loop.run_until_complete(do_request())
-
-
-class TestAioHttpIntegration(TestBase):
- def assert_spans(self, spans):
- self.assertEqual(
- [
- (
- span.name,
- (span.status.status_code, span.status.description),
- dict(span.attributes),
- )
- for span in self.memory_exporter.get_finished_spans()
- ],
- spans,
- )
-
- def test_url_path_span_name(self):
- for url, expected in (
- (
- yarl.URL("http://hostname.local:1234/some/path?query=params"),
- "/some/path",
- ),
- (yarl.URL("http://hostname.local:1234"), "/"),
- ):
- with self.subTest(url=url):
- params = aiohttp.TraceRequestStartParams("METHOD", url, {})
- actual = aiohttp_client.url_path_span_name(params)
- self.assertEqual(actual, expected)
- self.assertIsInstance(actual, str)
-
- @staticmethod
- def _http_request(
- trace_config,
- url: str,
- method: str = "GET",
- status_code: int = HTTPStatus.OK,
- request_handler: typing.Callable = None,
- **kwargs
- ) -> typing.Tuple[str, int]:
- """Helper to start an aiohttp test server and send an actual HTTP request to it."""
-
- async def default_handler(request):
- assert "traceparent" in request.headers
- return aiohttp.web.Response(status=int(status_code))
-
- async def client_request(server: aiohttp.test_utils.TestServer):
- async with aiohttp.test_utils.TestClient(
- server, trace_configs=[trace_config]
- ) as client:
- await client.request(
- method, url, trace_request_ctx={}, **kwargs
- )
-
- handler = request_handler or default_handler
- return run_with_test_server(client_request, url, handler)
-
- def test_status_codes(self):
- for status_code, span_status in (
- (HTTPStatus.OK, StatusCode.UNSET),
- (HTTPStatus.TEMPORARY_REDIRECT, StatusCode.UNSET),
- (HTTPStatus.SERVICE_UNAVAILABLE, StatusCode.ERROR),
- (HTTPStatus.GATEWAY_TIMEOUT, StatusCode.ERROR,),
- ):
- with self.subTest(status_code=status_code):
- host, port = self._http_request(
- trace_config=aiohttp_client.create_trace_config(),
- url="/test-path?query=param#foobar",
- status_code=status_code,
- )
-
- self.assert_spans(
- [
- (
- "HTTP GET",
- (span_status, None),
- {
- "component": "http",
- "http.method": "GET",
- "http.url": "http://{}:{}/test-path?query=param#foobar".format(
- host, port
- ),
- "http.status_code": int(status_code),
- "http.status_text": status_code.phrase,
- },
- )
- ]
- )
-
- self.memory_exporter.clear()
-
- def test_not_recording(self):
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- with mock.patch("opentelemetry.trace.get_tracer"):
- # pylint: disable=W0612
- host, port = self._http_request(
- trace_config=aiohttp_client.create_trace_config(),
- url="/test-path?query=param#foobar",
- )
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_span_name_option(self):
- for span_name, method, path, expected in (
- ("static", "POST", "/static-span-name", "static"),
- (
- lambda params: "{} - {}".format(
- params.method, params.url.path
- ),
- "PATCH",
- "/some/path",
- "PATCH - /some/path",
- ),
- ):
- with self.subTest(span_name=span_name, method=method, path=path):
- host, port = self._http_request(
- trace_config=aiohttp_client.create_trace_config(
- span_name=span_name
- ),
- method=method,
- url=path,
- status_code=HTTPStatus.OK,
- )
-
- self.assert_spans(
- [
- (
- expected,
- (StatusCode.UNSET, None),
- {
- "component": "http",
- "http.method": method,
- "http.url": "http://{}:{}{}".format(
- host, port, path
- ),
- "http.status_code": int(HTTPStatus.OK),
- "http.status_text": HTTPStatus.OK.phrase,
- },
- )
- ]
- )
- self.memory_exporter.clear()
-
- def test_url_filter_option(self):
- # Strips all query params from URL before adding as a span attribute.
- def strip_query_params(url: yarl.URL) -> str:
- return str(url.with_query(None))
-
- host, port = self._http_request(
- trace_config=aiohttp_client.create_trace_config(
- url_filter=strip_query_params
- ),
- url="/some/path?query=param&other=param2",
- status_code=HTTPStatus.OK,
- )
-
- self.assert_spans(
- [
- (
- "HTTP GET",
- (StatusCode.UNSET, None),
- {
- "component": "http",
- "http.method": "GET",
- "http.url": "http://{}:{}/some/path".format(
- host, port
- ),
- "http.status_code": int(HTTPStatus.OK),
- "http.status_text": HTTPStatus.OK.phrase,
- },
- )
- ]
- )
-
- def test_connection_errors(self):
- trace_configs = [aiohttp_client.create_trace_config()]
-
- for url, expected_status in (
- ("http://this-is-unknown.local/", StatusCode.ERROR),
- ("http://127.0.0.1:1/", StatusCode.ERROR),
- ):
- with self.subTest(expected_status=expected_status):
-
- async def do_request(url):
- async with aiohttp.ClientSession(
- trace_configs=trace_configs,
- ) as session:
- async with session.get(url):
- pass
-
- loop = asyncio.get_event_loop()
- with self.assertRaises(aiohttp.ClientConnectorError):
- loop.run_until_complete(do_request(url))
-
- self.assert_spans(
- [
- (
- "HTTP GET",
- (expected_status, None),
- {
- "component": "http",
- "http.method": "GET",
- "http.url": url,
- },
- )
- ]
- )
- self.memory_exporter.clear()
-
- def test_timeout(self):
- async def request_handler(request):
- await asyncio.sleep(1)
- assert "traceparent" in request.headers
- return aiohttp.web.Response()
-
- host, port = self._http_request(
- trace_config=aiohttp_client.create_trace_config(),
- url="/test_timeout",
- request_handler=request_handler,
- timeout=aiohttp.ClientTimeout(sock_read=0.01),
- )
-
- self.assert_spans(
- [
- (
- "HTTP GET",
- (StatusCode.ERROR, None),
- {
- "component": "http",
- "http.method": "GET",
- "http.url": "http://{}:{}/test_timeout".format(
- host, port
- ),
- },
- )
- ]
- )
-
- def test_too_many_redirects(self):
- async def request_handler(request):
- # Create a redirect loop.
- location = request.url
- assert "traceparent" in request.headers
- raise aiohttp.web.HTTPFound(location=location)
-
- host, port = self._http_request(
- trace_config=aiohttp_client.create_trace_config(),
- url="/test_too_many_redirects",
- request_handler=request_handler,
- max_redirects=2,
- )
-
- self.assert_spans(
- [
- (
- "HTTP GET",
- (StatusCode.ERROR, None),
- {
- "component": "http",
- "http.method": "GET",
- "http.url": "http://{}:{}/test_too_many_redirects".format(
- host, port
- ),
- },
- )
- ]
- )
-
-
-class TestAioHttpClientInstrumentor(TestBase):
- URL = "/test-path"
-
- def setUp(self):
- super().setUp()
- AioHttpClientInstrumentor().instrument()
-
- def tearDown(self):
- super().tearDown()
- AioHttpClientInstrumentor().uninstrument()
-
- @staticmethod
- # pylint:disable=unused-argument
- async def default_handler(request):
- return aiohttp.web.Response(status=int(200))
-
- @staticmethod
- def get_default_request(url: str = URL):
- async def default_request(server: aiohttp.test_utils.TestServer):
- async with aiohttp.test_utils.TestClient(server) as session:
- await session.get(url)
-
- return default_request
-
- def assert_spans(self, num_spans: int):
- finished_spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(num_spans, len(finished_spans))
- if num_spans == 0:
- return None
- if num_spans == 1:
- return finished_spans[0]
- return finished_spans
-
- def test_instrument(self):
- host, port = run_with_test_server(
- self.get_default_request(), self.URL, self.default_handler
- )
- span = self.assert_spans(1)
- self.assertEqual("http", span.attributes["component"])
- self.assertEqual("GET", span.attributes["http.method"])
- self.assertEqual(
- "http://{}:{}/test-path".format(host, port),
- span.attributes["http.url"],
- )
- self.assertEqual(200, span.attributes["http.status_code"])
- self.assertEqual("OK", span.attributes["http.status_text"])
-
- def test_instrument_with_existing_trace_config(self):
- trace_config = aiohttp.TraceConfig()
-
- async def create_session(server: aiohttp.test_utils.TestServer):
- async with aiohttp.test_utils.TestClient(
- server, trace_configs=[trace_config]
- ) as client:
- # pylint:disable=protected-access
- trace_configs = client.session._trace_configs
- self.assertEqual(2, len(trace_configs))
- self.assertTrue(trace_config in trace_configs)
- async with client as session:
- await session.get(TestAioHttpClientInstrumentor.URL)
-
- run_with_test_server(create_session, self.URL, self.default_handler)
- self.assert_spans(1)
-
- def test_uninstrument(self):
- AioHttpClientInstrumentor().uninstrument()
- run_with_test_server(
- self.get_default_request(), self.URL, self.default_handler
- )
-
- self.assert_spans(0)
-
- AioHttpClientInstrumentor().instrument()
- run_with_test_server(
- self.get_default_request(), self.URL, self.default_handler
- )
- self.assert_spans(1)
-
- def test_uninstrument_session(self):
- async def uninstrument_request(server: aiohttp.test_utils.TestServer):
- client = aiohttp.test_utils.TestClient(server)
- AioHttpClientInstrumentor().uninstrument_session(client.session)
- async with client as session:
- await session.get(self.URL)
-
- run_with_test_server(
- uninstrument_request, self.URL, self.default_handler
- )
- self.assert_spans(0)
-
- run_with_test_server(
- self.get_default_request(), self.URL, self.default_handler
- )
- self.assert_spans(1)
-
- def test_suppress_instrumentation(self):
- token = context.attach(
- context.set_value("suppress_instrumentation", True)
- )
- try:
- run_with_test_server(
- self.get_default_request(), self.URL, self.default_handler
- )
- finally:
- context.detach(token)
- self.assert_spans(0)
-
- @staticmethod
- async def suppressed_request(server: aiohttp.test_utils.TestServer):
- async with aiohttp.test_utils.TestClient(server) as client:
- token = context.attach(
- context.set_value("suppress_instrumentation", True)
- )
- await client.get(TestAioHttpClientInstrumentor.URL)
- context.detach(token)
-
- def test_suppress_instrumentation_after_creation(self):
- run_with_test_server(
- self.suppressed_request, self.URL, self.default_handler
- )
- self.assert_spans(0)
-
- def test_suppress_instrumentation_with_server_exception(self):
- # pylint:disable=unused-argument
- async def raising_handler(request):
- raise aiohttp.web.HTTPFound(location=self.URL)
-
- run_with_test_server(
- self.suppressed_request, self.URL, raising_handler
- )
- self.assert_spans(0)
-
- def test_url_filter(self):
- def strip_query_params(url: yarl.URL) -> str:
- return str(url.with_query(None))
-
- AioHttpClientInstrumentor().uninstrument()
- AioHttpClientInstrumentor().instrument(url_filter=strip_query_params)
-
- url = "/test-path?query=params"
- host, port = run_with_test_server(
- self.get_default_request(url), url, self.default_handler
- )
- span = self.assert_spans(1)
- self.assertEqual(
- "http://{}:{}/test-path".format(host, port),
- span.attributes["http.url"],
- )
-
- def test_span_name(self):
- def span_name_callback(params: aiohttp.TraceRequestStartParams) -> str:
- return "{} - {}".format(params.method, params.url.path)
-
- AioHttpClientInstrumentor().uninstrument()
- AioHttpClientInstrumentor().instrument(span_name=span_name_callback)
-
- url = "/test-path"
- run_with_test_server(
- self.get_default_request(url), url, self.default_handler
- )
- span = self.assert_spans(1)
- self.assertEqual("GET - /test-path", span.name)
-
-
-class TestLoadingAioHttpInstrumentor(unittest.TestCase):
- def test_loading_instrumentor(self):
- entry_points = iter_entry_points(
- "opentelemetry_instrumentor", "aiohttp-client"
- )
-
- instrumentor = next(entry_points).load()()
- self.assertIsInstance(instrumentor, AioHttpClientInstrumentor)
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-aiopg/CHANGELOG.md
deleted file mode 100644
index c62fac06178..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/CHANGELOG.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.11b0
-
-Released 2020-07-28
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/LICENSE b/instrumentation/opentelemetry-instrumentation-aiopg/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-aiopg/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-aiopg/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/README.rst b/instrumentation/opentelemetry-instrumentation-aiopg/README.rst
deleted file mode 100644
index f7a66579dfc..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/README.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-OpenTelemetry aiopg instrumentation
-===================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-aiopg.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-aiopg/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-aiopg
-
-
-References
-----------
-
-* `OpenTelemetry aiopg Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/setup.cfg b/instrumentation/opentelemetry-instrumentation-aiopg/setup.cfg
deleted file mode 100644
index c903180e98f..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/setup.cfg
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-aiopg
-description = OpenTelemetry aiopg instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-aiopg
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation-dbapi == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- aiopg >= 0.13.0
- wrapt >= 1.0.0, < 2.0.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-
-[options.entry_points]
-opentelemetry_instrumentor =
- aiopg = opentelemetry.instrumentation.aiopg:AiopgInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/setup.py b/instrumentation/opentelemetry-instrumentation-aiopg/setup.py
deleted file mode 100644
index dfd463e5abb..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "aiopg", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py
deleted file mode 100644
index 176fc82b40c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-The integration with PostgreSQL supports the aiopg library,
-it can be enabled by using ``AiopgInstrumentor``.
-
-.. aiopg: https://github.com/aio-libs/aiopg
-
-Usage
------
-
-.. code-block:: python
-
- import aiopg
- from opentelemetry.instrumentation.aiopg import AiopgInstrumentor
-
- AiopgInstrumentor().instrument()
-
- cnx = await aiopg.connect(database='Database')
- cursor = await cnx.cursor()
- await cursor.execute("INSERT INTO test (testField) VALUES (123)")
- cursor.close()
- cnx.close()
-
- pool = await aiopg.create_pool(database='Database')
- cnx = await pool.acquire()
- cursor = await cnx.cursor()
- await cursor.execute("INSERT INTO test (testField) VALUES (123)")
- cursor.close()
- cnx.close()
-
-API
----
-"""
-
-from opentelemetry.instrumentation.aiopg import wrappers
-from opentelemetry.instrumentation.aiopg.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-
-
-class AiopgInstrumentor(BaseInstrumentor):
- _CONNECTION_ATTRIBUTES = {
- "database": "info.dbname",
- "port": "info.port",
- "host": "info.host",
- "user": "info.user",
- }
-
- _DATABASE_COMPONENT = "postgresql"
- _DATABASE_TYPE = "sql"
-
- def _instrument(self, **kwargs):
- """Integrate with PostgreSQL aiopg library.
- aiopg: https://github.com/aio-libs/aiopg
- """
-
- tracer_provider = kwargs.get("tracer_provider")
-
- wrappers.wrap_connect(
- __name__,
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- version=__version__,
- tracer_provider=tracer_provider,
- )
-
- wrappers.wrap_create_pool(
- __name__,
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- version=__version__,
- tracer_provider=tracer_provider,
- )
-
- def _uninstrument(self, **kwargs):
- """"Disable aiopg instrumentation"""
- wrappers.unwrap_connect()
- wrappers.unwrap_create_pool()
-
- # pylint:disable=no-self-use
- def instrument_connection(self, connection):
- """Enable instrumentation in a aiopg connection.
-
- Args:
- connection: The connection to instrument.
-
- Returns:
- An instrumented connection.
- """
- return wrappers.instrument_connection(
- __name__,
- connection,
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- )
-
- def uninstrument_connection(self, connection):
- """Disable instrumentation in a aiopg connection.
-
- Args:
- connection: The connection to uninstrument.
-
- Returns:
- An uninstrumented connection.
- """
- return wrappers.uninstrument_connection(connection)
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py
deleted file mode 100644
index 14f986da065..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py
+++ /dev/null
@@ -1,146 +0,0 @@
-import typing
-
-import wrapt
-from aiopg.utils import _ContextManager, _PoolAcquireContextManager
-
-from opentelemetry.instrumentation.dbapi import (
- DatabaseApiIntegration,
- TracedCursor,
-)
-from opentelemetry.trace import SpanKind
-from opentelemetry.trace.status import Status, StatusCode
-
-
-# pylint: disable=abstract-method
-class AsyncProxyObject(wrapt.ObjectProxy):
- def __aiter__(self):
- return self.__wrapped__.__aiter__()
-
- async def __anext__(self):
- result = await self.__wrapped__.__anext__()
- return result
-
- async def __aenter__(self):
- return await self.__wrapped__.__aenter__()
-
- async def __aexit__(self, exc_type, exc_val, exc_tb):
- return await self.__wrapped__.__aexit__(exc_type, exc_val, exc_tb)
-
- def __await__(self):
- return self.__wrapped__.__await__()
-
-
-class AiopgIntegration(DatabaseApiIntegration):
- async def wrapped_connection(
- self,
- connect_method: typing.Callable[..., typing.Any],
- args: typing.Tuple[typing.Any, typing.Any],
- kwargs: typing.Dict[typing.Any, typing.Any],
- ):
- """Add object proxy to connection object."""
- connection = await connect_method(*args, **kwargs)
- # pylint: disable=protected-access
- self.get_connection_attributes(connection._conn)
- return get_traced_connection_proxy(connection, self)
-
- async def wrapped_pool(self, create_pool_method, args, kwargs):
- pool = await create_pool_method(*args, **kwargs)
- async with pool.acquire() as connection:
- # pylint: disable=protected-access
- self.get_connection_attributes(connection._conn)
- return get_traced_pool_proxy(pool, self)
-
-
-def get_traced_connection_proxy(
- connection, db_api_integration, *args, **kwargs
-):
- # pylint: disable=abstract-method
- class TracedConnectionProxy(AsyncProxyObject):
- # pylint: disable=unused-argument
- def __init__(self, connection, *args, **kwargs):
- super().__init__(connection)
-
- def cursor(self, *args, **kwargs):
- coro = self._cursor(*args, **kwargs)
- return _ContextManager(coro)
-
- async def _cursor(self, *args, **kwargs):
- # pylint: disable=protected-access
- cursor = await self.__wrapped__._cursor(*args, **kwargs)
- return get_traced_cursor_proxy(cursor, db_api_integration)
-
- return TracedConnectionProxy(connection, *args, **kwargs)
-
-
-def get_traced_pool_proxy(pool, db_api_integration, *args, **kwargs):
- # pylint: disable=abstract-method
- class TracedPoolProxy(AsyncProxyObject):
- # pylint: disable=unused-argument
- def __init__(self, pool, *args, **kwargs):
- super().__init__(pool)
-
- def acquire(self):
- """Acquire free connection from the pool."""
- coro = self._acquire()
- return _PoolAcquireContextManager(coro, self)
-
- async def _acquire(self):
- # pylint: disable=protected-access
- connection = await self.__wrapped__._acquire()
- return get_traced_connection_proxy(
- connection, db_api_integration, *args, **kwargs
- )
-
- return TracedPoolProxy(pool, *args, **kwargs)
-
-
-class AsyncTracedCursor(TracedCursor):
- async def traced_execution(
- self,
- query_method: typing.Callable[..., typing.Any],
- *args: typing.Tuple[typing.Any, typing.Any],
- **kwargs: typing.Dict[typing.Any, typing.Any]
- ):
-
- with self._db_api_integration.get_tracer().start_as_current_span(
- self._db_api_integration.name, kind=SpanKind.CLIENT
- ) as span:
- self._populate_span(span, *args)
- try:
- result = await query_method(*args, **kwargs)
- return result
- except Exception as ex: # pylint: disable=broad-except
- if span.is_recording():
- span.set_status(Status(StatusCode.ERROR, str(ex)))
- raise ex
-
-
-def get_traced_cursor_proxy(cursor, db_api_integration, *args, **kwargs):
- _traced_cursor = AsyncTracedCursor(db_api_integration)
-
- # pylint: disable=abstract-method
- class AsyncTracedCursorProxy(AsyncProxyObject):
-
- # pylint: disable=unused-argument
- def __init__(self, cursor, *args, **kwargs):
- super().__init__(cursor)
-
- async def execute(self, *args, **kwargs):
- result = await _traced_cursor.traced_execution(
- self.__wrapped__.execute, *args, **kwargs
- )
- return result
-
- async def executemany(self, *args, **kwargs):
- result = await _traced_cursor.traced_execution(
- self.__wrapped__.executemany, *args, **kwargs
- )
- return result
-
- async def callproc(self, *args, **kwargs):
- result = await _traced_cursor.traced_execution(
- self.__wrapped__.callproc, *args, **kwargs
- )
- return result
-
- return AsyncTracedCursorProxy(cursor, *args, **kwargs)
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/version.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py
deleted file mode 100644
index 8a3b6023bd5..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py
+++ /dev/null
@@ -1,223 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-The trace integration with aiopg based on dbapi integration,
-where replaced sync wrap methods to async
-
-Usage
------
-
-.. code-block:: python
-
- from opentelemetry import trace
- from opentelemetry.instrumentation.aiopg import trace_integration
- from opentelemetry.trace import TracerProvider
-
- trace.set_tracer_provider(TracerProvider())
-
- trace_integration(aiopg.connection, "_connect", "postgresql", "sql")
-
-API
----
-"""
-import logging
-import typing
-
-import aiopg
-import wrapt
-
-from opentelemetry.instrumentation.aiopg.aiopg_integration import (
- AiopgIntegration,
- get_traced_connection_proxy,
-)
-from opentelemetry.instrumentation.aiopg.version import __version__
-from opentelemetry.instrumentation.utils import unwrap
-from opentelemetry.trace import TracerProvider
-
-logger = logging.getLogger(__name__)
-
-
-def trace_integration(
- database_component: str,
- database_type: str = "",
- connection_attributes: typing.Dict = None,
- tracer_provider: typing.Optional[TracerProvider] = None,
-):
- """Integrate with aiopg library.
- based on dbapi integration, where replaced sync wrap methods to async
-
- Args:
- database_component: Database driver name or
- database name "postgreSQL".
- database_type: The Database type. For any SQL database, "sql".
- connection_attributes: Attribute names for database, port, host and
- user in Connection object.
- tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to
- use. If ommited the current configured one is used.
- """
-
- wrap_connect(
- __name__,
- database_component,
- database_type,
- connection_attributes,
- __version__,
- tracer_provider,
- )
-
-
-def wrap_connect(
- name: str,
- database_component: str,
- database_type: str = "",
- connection_attributes: typing.Dict = None,
- version: str = "",
- tracer_provider: typing.Optional[TracerProvider] = None,
-):
- """Integrate with aiopg library.
- https://github.com/aio-libs/aiopg
-
- Args:
- name: Name of opentelemetry extension for aiopg.
- database_component: Database driver name
- or database name "postgreSQL".
- database_type: The Database type. For any SQL database, "sql".
- connection_attributes: Attribute names for database, port, host and
- user in Connection object.
- version: Version of opentelemetry extension for aiopg.
- tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to
- use. If ommited the current configured one is used.
- """
-
- # pylint: disable=unused-argument
- async def wrap_connect_(
- wrapped: typing.Callable[..., typing.Any],
- instance: typing.Any,
- args: typing.Tuple[typing.Any, typing.Any],
- kwargs: typing.Dict[typing.Any, typing.Any],
- ):
- db_integration = AiopgIntegration(
- name,
- database_component,
- database_type=database_type,
- connection_attributes=connection_attributes,
- version=version,
- tracer_provider=tracer_provider,
- )
- return await db_integration.wrapped_connection(wrapped, args, kwargs)
-
- try:
- wrapt.wrap_function_wrapper(aiopg, "connect", wrap_connect_)
- except Exception as ex: # pylint: disable=broad-except
- logger.warning("Failed to integrate with aiopg. %s", str(ex))
-
-
-def unwrap_connect():
- """Disable integration with aiopg library.
- https://github.com/aio-libs/aiopg
- """
-
- unwrap(aiopg, "connect")
-
-
-def instrument_connection(
- name: str,
- connection,
- database_component: str,
- database_type: str = "",
- connection_attributes: typing.Dict = None,
- version: str = "",
- tracer_provider: typing.Optional[TracerProvider] = None,
-):
- """Enable instrumentation in a database connection.
-
- Args:
- name: Name of opentelemetry extension for aiopg.
- connection: The connection to instrument.
- database_component: Database driver name or database name "postgreSQL".
- database_type: The Database type. For any SQL database, "sql".
- connection_attributes: Attribute names for database, port, host and
- user in a connection object.
- version: Version of opentelemetry extension for aiopg.
- tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to
- use. If ommited the current configured one is used.
-
- Returns:
- An instrumented connection.
- """
- db_integration = AiopgIntegration(
- name,
- database_component,
- database_type,
- connection_attributes=connection_attributes,
- version=version,
- tracer_provider=tracer_provider,
- )
- db_integration.get_connection_attributes(connection)
- return get_traced_connection_proxy(connection, db_integration)
-
-
-def uninstrument_connection(connection):
- """Disable instrumentation in a database connection.
-
- Args:
- connection: The connection to uninstrument.
-
- Returns:
- An uninstrumented connection.
- """
- if isinstance(connection, wrapt.ObjectProxy):
- return connection.__wrapped__
-
- logger.warning("Connection is not instrumented")
- return connection
-
-
-def wrap_create_pool(
- name: str,
- database_component: str,
- database_type: str = "",
- connection_attributes: typing.Dict = None,
- version: str = "",
- tracer_provider: typing.Optional[TracerProvider] = None,
-):
- # pylint: disable=unused-argument
- async def wrap_create_pool_(
- wrapped: typing.Callable[..., typing.Any],
- instance: typing.Any,
- args: typing.Tuple[typing.Any, typing.Any],
- kwargs: typing.Dict[typing.Any, typing.Any],
- ):
- db_integration = AiopgIntegration(
- name,
- database_component,
- database_type,
- connection_attributes=connection_attributes,
- version=version,
- tracer_provider=tracer_provider,
- )
- return await db_integration.wrapped_pool(wrapped, args, kwargs)
-
- try:
- wrapt.wrap_function_wrapper(aiopg, "create_pool", wrap_create_pool_)
- except Exception as ex: # pylint: disable=broad-except
- logger.warning("Failed to integrate with DB API. %s", str(ex))
-
-
-def unwrap_create_pool():
- """Disable integration with aiopg library.
- https://github.com/aio-libs/aiopg
- """
- unwrap(aiopg, "create_pool")
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-aiopg/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py
deleted file mode 100644
index 78ea4552e23..00000000000
--- a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py
+++ /dev/null
@@ -1,504 +0,0 @@
-# Copyright The OpenTelemetry 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 asyncio
-import logging
-from unittest import mock
-from unittest.mock import MagicMock
-
-import aiopg
-from aiopg.utils import _ContextManager, _PoolAcquireContextManager
-
-import opentelemetry.instrumentation.aiopg
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.aiopg import AiopgInstrumentor, wrappers
-from opentelemetry.instrumentation.aiopg.aiopg_integration import (
- AiopgIntegration,
-)
-from opentelemetry.sdk import resources
-from opentelemetry.test.test_base import TestBase
-
-
-def async_call(coro):
- loop = asyncio.get_event_loop()
- return loop.run_until_complete(coro)
-
-
-class TestAiopgInstrumentor(TestBase):
- def setUp(self):
- super().setUp()
- self.origin_aiopg_connect = aiopg.connect
- self.origin_aiopg_create_pool = aiopg.create_pool
- aiopg.connect = mock_connect
- aiopg.create_pool = mock_create_pool
-
- def tearDown(self):
- super().tearDown()
- aiopg.connect = self.origin_aiopg_connect
- aiopg.create_pool = self.origin_aiopg_create_pool
- with self.disable_logging():
- AiopgInstrumentor().uninstrument()
-
- def test_instrumentor_connect(self):
- AiopgInstrumentor().instrument()
-
- cnx = async_call(aiopg.connect(database="test"))
-
- cursor = async_call(cnx.cursor())
-
- query = "SELECT * FROM test"
- async_call(cursor.execute(query))
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.aiopg
- )
-
- # check that no spans are generated after uninstrument
- AiopgInstrumentor().uninstrument()
-
- cnx = async_call(aiopg.connect(database="test"))
- cursor = async_call(cnx.cursor())
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- def test_instrumentor_create_pool(self):
- AiopgInstrumentor().instrument()
-
- pool = async_call(aiopg.create_pool(database="test"))
- cnx = async_call(pool.acquire())
- cursor = async_call(cnx.cursor())
-
- query = "SELECT * FROM test"
- async_call(cursor.execute(query))
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.aiopg
- )
-
- # check that no spans are generated after uninstrument
- AiopgInstrumentor().uninstrument()
-
- pool = async_call(aiopg.create_pool(database="test"))
- cnx = async_call(pool.acquire())
- cursor = async_call(cnx.cursor())
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- def test_custom_tracer_provider_connect(self):
- resource = resources.Resource.create({})
- result = self.create_tracer_provider(resource=resource)
- tracer_provider, exporter = result
-
- AiopgInstrumentor().instrument(tracer_provider=tracer_provider)
-
- cnx = async_call(aiopg.connect(database="test"))
- cursor = async_call(cnx.cursor())
- query = "SELECT * FROM test"
- async_call(cursor.execute(query))
-
- spans_list = exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertIs(span.resource, resource)
-
- def test_custom_tracer_provider_create_pool(self):
- resource = resources.Resource.create({})
- result = self.create_tracer_provider(resource=resource)
- tracer_provider, exporter = result
-
- AiopgInstrumentor().instrument(tracer_provider=tracer_provider)
-
- pool = async_call(aiopg.create_pool(database="test"))
- cnx = async_call(pool.acquire())
- cursor = async_call(cnx.cursor())
- query = "SELECT * FROM test"
- async_call(cursor.execute(query))
-
- spans_list = exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- self.assertIs(span.resource, resource)
-
- def test_instrument_connection(self):
- cnx = async_call(aiopg.connect(database="test"))
- query = "SELECT * FROM test"
- cursor = async_call(cnx.cursor())
- async_call(cursor.execute(query))
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 0)
-
- cnx = AiopgInstrumentor().instrument_connection(cnx)
- cursor = async_call(cnx.cursor())
- async_call(cursor.execute(query))
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- def test_uninstrument_connection(self):
- AiopgInstrumentor().instrument()
- cnx = async_call(aiopg.connect(database="test"))
- query = "SELECT * FROM test"
- cursor = async_call(cnx.cursor())
- async_call(cursor.execute(query))
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- cnx = AiopgInstrumentor().uninstrument_connection(cnx)
- cursor = async_call(cnx.cursor())
- async_call(cursor.execute(query))
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
-
-class TestAiopgIntegration(TestBase):
- def setUp(self):
- super().setUp()
- self.tracer = self.tracer_provider.get_tracer(__name__)
-
- def test_span_succeeded(self):
- connection_props = {
- "database": "testdatabase",
- "server_host": "testhost",
- "server_port": 123,
- "user": "testuser",
- }
- connection_attributes = {
- "database": "database",
- "port": "server_port",
- "host": "server_host",
- "user": "user",
- }
- db_integration = AiopgIntegration(
- self.tracer, "testcomponent", "testtype", connection_attributes
- )
- mock_connection = async_call(
- db_integration.wrapped_connection(
- mock_connect, {}, connection_props
- )
- )
- cursor = async_call(mock_connection.cursor())
- async_call(cursor.execute("Test query", ("param1Value", False)))
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(span.name, "testcomponent.testdatabase")
- self.assertIs(span.kind, trace_api.SpanKind.CLIENT)
-
- self.assertEqual(span.attributes["component"], "testcomponent")
- self.assertEqual(span.attributes["db.type"], "testtype")
- self.assertEqual(span.attributes["db.instance"], "testdatabase")
- self.assertEqual(span.attributes["db.statement"], "Test query")
- self.assertEqual(
- span.attributes["db.statement.parameters"],
- "('param1Value', False)",
- )
- self.assertEqual(span.attributes["db.user"], "testuser")
- self.assertEqual(span.attributes["net.peer.name"], "testhost")
- self.assertEqual(span.attributes["net.peer.port"], 123)
- self.assertIs(
- span.status.status_code, trace_api.status.StatusCode.UNSET,
- )
-
- def test_span_not_recording(self):
- connection_props = {
- "database": "testdatabase",
- "server_host": "testhost",
- "server_port": 123,
- "user": "testuser",
- }
- connection_attributes = {
- "database": "database",
- "port": "server_port",
- "host": "server_host",
- "user": "user",
- }
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- db_integration = AiopgIntegration(
- mock_tracer, "testcomponent", "testtype", connection_attributes
- )
- mock_connection = async_call(
- db_integration.wrapped_connection(
- mock_connect, {}, connection_props
- )
- )
- cursor = async_call(mock_connection.cursor())
- async_call(cursor.execute("Test query", ("param1Value", False)))
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_span_failed(self):
- db_integration = AiopgIntegration(self.tracer, "testcomponent")
- mock_connection = async_call(
- db_integration.wrapped_connection(mock_connect, {}, {})
- )
- cursor = async_call(mock_connection.cursor())
- with self.assertRaises(Exception):
- async_call(cursor.execute("Test query", throw_exception=True))
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(span.attributes["db.statement"], "Test query")
- self.assertIs(
- span.status.status_code, trace_api.status.StatusCode.ERROR,
- )
- self.assertEqual(span.status.description, "Test Exception")
-
- def test_executemany(self):
- db_integration = AiopgIntegration(self.tracer, "testcomponent")
- mock_connection = async_call(
- db_integration.wrapped_connection(mock_connect, {}, {})
- )
- cursor = async_call(mock_connection.cursor())
- async_call(cursor.executemany("Test query"))
- spans_list = self.memory_exporter.get_finished_spans()
-
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(span.attributes["db.statement"], "Test query")
-
- def test_callproc(self):
- db_integration = AiopgIntegration(self.tracer, "testcomponent")
- mock_connection = async_call(
- db_integration.wrapped_connection(mock_connect, {}, {})
- )
- cursor = async_call(mock_connection.cursor())
- async_call(cursor.callproc("Test stored procedure"))
- spans_list = self.memory_exporter.get_finished_spans()
-
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(
- span.attributes["db.statement"], "Test stored procedure"
- )
-
- def test_wrap_connect(self):
- aiopg_mock = AiopgMock()
- with mock.patch("aiopg.connect", aiopg_mock.connect):
- wrappers.wrap_connect(self.tracer, "-")
- connection = async_call(aiopg.connect())
- self.assertEqual(aiopg_mock.connect_call_count, 1)
- self.assertIsInstance(connection.__wrapped__, mock.Mock)
-
- def test_unwrap_connect(self):
- wrappers.wrap_connect(self.tracer, "-")
- aiopg_mock = AiopgMock()
- with mock.patch("aiopg.connect", aiopg_mock.connect):
- connection = async_call(aiopg.connect())
- self.assertEqual(aiopg_mock.connect_call_count, 1)
- wrappers.unwrap_connect()
- connection = async_call(aiopg.connect())
- self.assertEqual(aiopg_mock.connect_call_count, 2)
- self.assertIsInstance(connection, mock.Mock)
-
- def test_wrap_create_pool(self):
- async def check_connection(pool):
- async with pool.acquire() as connection:
- self.assertEqual(aiopg_mock.create_pool_call_count, 1)
- self.assertIsInstance(
- connection.__wrapped__, AiopgConnectionMock
- )
-
- aiopg_mock = AiopgMock()
- with mock.patch("aiopg.create_pool", aiopg_mock.create_pool):
- wrappers.wrap_create_pool(self.tracer, "-")
- pool = async_call(aiopg.create_pool())
- async_call(check_connection(pool))
-
- def test_unwrap_create_pool(self):
- async def check_connection(pool):
- async with pool.acquire() as connection:
- self.assertEqual(aiopg_mock.create_pool_call_count, 2)
- self.assertIsInstance(connection, AiopgConnectionMock)
-
- aiopg_mock = AiopgMock()
- with mock.patch("aiopg.create_pool", aiopg_mock.create_pool):
- wrappers.wrap_create_pool(self.tracer, "-")
- pool = async_call(aiopg.create_pool())
- self.assertEqual(aiopg_mock.create_pool_call_count, 1)
-
- wrappers.unwrap_create_pool()
- pool = async_call(aiopg.create_pool())
- async_call(check_connection(pool))
-
- def test_instrument_connection(self):
- connection = mock.Mock()
- # Avoid get_attributes failing because can't concatenate mock
- connection.database = "-"
- connection2 = wrappers.instrument_connection(
- self.tracer, connection, "-"
- )
- self.assertIs(connection2.__wrapped__, connection)
-
- def test_uninstrument_connection(self):
- connection = mock.Mock()
- # Set connection.database to avoid a failure because mock can't
- # be concatenated
- connection.database = "-"
- connection2 = wrappers.instrument_connection(
- self.tracer, connection, "-"
- )
- self.assertIs(connection2.__wrapped__, connection)
-
- connection3 = wrappers.uninstrument_connection(connection2)
- self.assertIs(connection3, connection)
-
- with self.assertLogs(level=logging.WARNING):
- connection4 = wrappers.uninstrument_connection(connection)
- self.assertIs(connection4, connection)
-
-
-# pylint: disable=unused-argument
-async def mock_connect(*args, **kwargs):
- database = kwargs.get("database")
- server_host = kwargs.get("server_host")
- server_port = kwargs.get("server_port")
- user = kwargs.get("user")
- return MockConnection(database, server_port, server_host, user)
-
-
-# pylint: disable=unused-argument
-async def mock_create_pool(*args, **kwargs):
- database = kwargs.get("database")
- server_host = kwargs.get("server_host")
- server_port = kwargs.get("server_port")
- user = kwargs.get("user")
- return MockPool(database, server_port, server_host, user)
-
-
-class MockPool:
- def __init__(self, database, server_port, server_host, user):
- self.database = database
- self.server_port = server_port
- self.server_host = server_host
- self.user = user
-
- async def release(self, conn):
- return conn
-
- def acquire(self):
- """Acquire free connection from the pool."""
- coro = self._acquire()
- return _PoolAcquireContextManager(coro, self)
-
- async def _acquire(self):
- connect = await mock_connect(
- self.database, self.server_port, self.server_host, self.user
- )
- return connect
-
-
-class MockPsycopg2Connection:
- def __init__(self, database, server_port, server_host, user):
- self.database = database
- self.server_port = server_port
- self.server_host = server_host
- self.user = user
-
-
-class MockConnection:
- def __init__(self, database, server_port, server_host, user):
- self._conn = MockPsycopg2Connection(
- database, server_port, server_host, user
- )
-
- # pylint: disable=no-self-use
- def cursor(self):
- coro = self._cursor()
- return _ContextManager(coro)
-
- async def _cursor(self):
- return MockCursor()
-
- def close(self):
- pass
-
-
-class MockCursor:
- # pylint: disable=unused-argument, no-self-use
- async def execute(self, query, params=None, throw_exception=False):
- if throw_exception:
- raise Exception("Test Exception")
-
- # pylint: disable=unused-argument, no-self-use
- async def executemany(self, query, params=None, throw_exception=False):
- if throw_exception:
- raise Exception("Test Exception")
-
- # pylint: disable=unused-argument, no-self-use
- async def callproc(self, query, params=None, throw_exception=False):
- if throw_exception:
- raise Exception("Test Exception")
-
-
-class AiopgConnectionMock:
- _conn = MagicMock()
-
- async def __aexit__(self, exc_type, exc_val, exc_tb):
- pass
-
- async def __aenter__(self):
- return MagicMock()
-
-
-class AiopgPoolMock:
- async def release(self, conn):
- return conn
-
- def acquire(self):
- coro = self._acquire()
- return _PoolAcquireContextManager(coro, self)
-
- async def _acquire(self):
- return AiopgConnectionMock()
-
-
-class AiopgMock:
- def __init__(self):
- self.connect_call_count = 0
- self.create_pool_call_count = 0
-
- async def connect(self, *args, **kwargs):
- self.connect_call_count += 1
- return MagicMock()
-
- async def create_pool(self, *args, **kwargs):
- self.create_pool_call_count += 1
- return AiopgPoolMock()
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-asgi/CHANGELOG.md
deleted file mode 100644
index 686b8cf830a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asgi/CHANGELOG.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-asgi
- ([#961](https://github.com/open-telemetry/opentelemetry-python/pull/961))
-
-## 0.8b0
-
-Released 2020-05-27
-
-- Add ASGI middleware ([#716](https://github.com/open-telemetry/opentelemetry-python/pull/716))
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/README.rst b/instrumentation/opentelemetry-instrumentation-asgi/README.rst
deleted file mode 100644
index 3eb8e2dda72..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asgi/README.rst
+++ /dev/null
@@ -1,71 +0,0 @@
-OpenTelemetry ASGI Instrumentation
-==================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-asgi.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-asgi/
-
-
-This library provides a ASGI middleware that can be used on any ASGI framework
-(such as Django, Starlette, FastAPI or Quart) to track requests timing through OpenTelemetry.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-asgi
-
-
-Usage (Quart)
--------------
-
-.. code-block:: python
-
- from quart import Quart
- from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
-
- app = Quart(__name__)
- app.asgi_app = OpenTelemetryMiddleware(app.asgi_app)
-
- @app.route("/")
- async def hello():
- return "Hello!"
-
- if __name__ == "__main__":
- app.run(debug=True)
-
-
-Usage (Django 3.0)
-------------------
-
-Modify the application's ``asgi.py`` file as shown below.
-
-.. code-block:: python
-
- import os
- from django.core.asgi import get_asgi_application
- from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
-
- os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'asgi_example.settings')
-
- application = get_asgi_application()
- application = OpenTelemetryMiddleware(application)
-
-
-Usage (Raw ASGI)
-----------------
-
-.. code-block:: python
-
- from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
-
- app = ... # An ASGI application.
- app = OpenTelemetryMiddleware(app)
-
-
-References
-----------
-
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/setup.cfg b/instrumentation/opentelemetry-instrumentation-asgi/setup.cfg
deleted file mode 100644
index dafb8379437..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asgi/setup.cfg
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-asgi
-description = ASGI instrumentation for OpenTelemetry
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/instrumentation/opentelemetry-instrumentation-asgi
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- asgiref ~= 3.0
-
-[options.extras_require]
-test =
- opentelemetry-test
-
-[options.packages.find]
-where = src
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/setup.py b/instrumentation/opentelemetry-instrumentation-asgi/setup.py
deleted file mode 100644
index 3369352fe1e..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asgi/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "asgi", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py
deleted file mode 100644
index 1c442889a1b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py
+++ /dev/null
@@ -1,208 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-The opentelemetry-instrumentation-asgi package provides an ASGI middleware that can be used
-on any ASGI framework (such as Django-channels / Quart) to track requests
-timing through OpenTelemetry.
-"""
-
-import operator
-import typing
-import urllib
-from functools import wraps
-from typing import Tuple
-
-from asgiref.compatibility import guarantee_single_callable
-
-from opentelemetry import context, propagators, trace
-from opentelemetry.instrumentation.asgi.version import __version__ # noqa
-from opentelemetry.instrumentation.utils import http_status_to_status_code
-from opentelemetry.trace.propagation.textmap import DictGetter
-from opentelemetry.trace.status import Status, StatusCode
-
-
-class CarrierGetter(DictGetter):
- def get(self, carrier: dict, key: str) -> typing.List[str]:
- """Getter implementation to retrieve a HTTP header value from the ASGI
- scope.
-
- Args:
- carrier: ASGI scope object
- key: header name in scope
- Returns:
- A list with a single string with the header value if it exists,
- else an empty list.
- """
- headers = carrier.get("headers")
- return [
- _value.decode("utf8")
- for (_key, _value) in headers
- if _key.decode("utf8") == key
- ]
-
-
-carrier_getter = CarrierGetter()
-
-
-def collect_request_attributes(scope):
- """Collects HTTP request attributes from the ASGI scope and returns a
- dictionary to be used as span creation attributes."""
- server = scope.get("server") or ["0.0.0.0", 80]
- port = server[1]
- server_host = server[0] + (":" + str(port) if port != 80 else "")
- full_path = scope.get("root_path", "") + scope.get("path", "")
- http_url = scope.get("scheme", "http") + "://" + server_host + full_path
- query_string = scope.get("query_string")
- if query_string and http_url:
- if isinstance(query_string, bytes):
- query_string = query_string.decode("utf8")
- http_url = http_url + ("?" + urllib.parse.unquote(query_string))
-
- result = {
- "component": scope["type"],
- "http.scheme": scope.get("scheme"),
- "http.host": server_host,
- "host.port": port,
- "http.flavor": scope.get("http_version"),
- "http.target": scope.get("path"),
- "http.url": http_url,
- }
- http_method = scope.get("method")
- if http_method:
- result["http.method"] = http_method
- http_host_value = ",".join(carrier_getter.get(scope, "host"))
- if http_host_value:
- result["http.server_name"] = http_host_value
- http_user_agent = carrier_getter.get(scope, "user-agent")
- if len(http_user_agent) > 0:
- result["http.user_agent"] = http_user_agent[0]
-
- if "client" in scope and scope["client"] is not None:
- result["net.peer.ip"] = scope.get("client")[0]
- result["net.peer.port"] = scope.get("client")[1]
-
- # remove None values
- result = {k: v for k, v in result.items() if v is not None}
-
- return result
-
-
-def set_status_code(span, status_code):
- """Adds HTTP response attributes to span using the status_code argument."""
- if not span.is_recording():
- return
- try:
- status_code = int(status_code)
- except ValueError:
- span.set_status(
- Status(
- StatusCode.ERROR,
- "Non-integer HTTP status: " + repr(status_code),
- )
- )
- else:
- span.set_attribute("http.status_code", status_code)
- span.set_status(Status(http_status_to_status_code(status_code)))
-
-
-def get_default_span_details(scope: dict) -> Tuple[str, dict]:
- """Default implementation for span_details_callback
-
- Args:
- scope: the asgi scope dictionary
-
- Returns:
- a tuple of the span, and any attributes to attach to the
- span.
- """
- method_or_path = scope.get("method") or scope.get("path")
-
- return method_or_path, {}
-
-
-class OpenTelemetryMiddleware:
- """The ASGI application middleware.
-
- This class is an ASGI middleware that starts and annotates spans for any
- requests it is invoked with.
-
- Args:
- app: The ASGI application callable to forward requests to.
- span_details_callback: Callback which should return a string
- and a tuple, representing the desired span name and a
- dictionary with any additional span attributes to set.
- Optional: Defaults to get_default_span_details.
- """
-
- def __init__(self, app, span_details_callback=None):
- self.app = guarantee_single_callable(app)
- self.tracer = trace.get_tracer(__name__, __version__)
- self.span_details_callback = (
- span_details_callback or get_default_span_details
- )
-
- async def __call__(self, scope, receive, send):
- """The ASGI application
-
- Args:
- scope: A ASGI environment.
- receive: An awaitable callable yielding dictionaries
- send: An awaitable callable taking a single dictionary as argument.
- """
- if scope["type"] not in ("http", "websocket"):
- return await self.app(scope, receive, send)
-
- token = context.attach(propagators.extract(carrier_getter, scope))
- span_name, additional_attributes = self.span_details_callback(scope)
-
- try:
- with self.tracer.start_as_current_span(
- span_name + " asgi", kind=trace.SpanKind.SERVER,
- ) as span:
- if span.is_recording():
- attributes = collect_request_attributes(scope)
- attributes.update(additional_attributes)
- for key, value in attributes.items():
- span.set_attribute(key, value)
-
- @wraps(receive)
- async def wrapped_receive():
- with self.tracer.start_as_current_span(
- span_name + " asgi." + scope["type"] + ".receive"
- ) as receive_span:
- message = await receive()
- if receive_span.is_recording():
- if message["type"] == "websocket.receive":
- set_status_code(receive_span, 200)
- receive_span.set_attribute("type", message["type"])
- return message
-
- @wraps(send)
- async def wrapped_send(message):
- with self.tracer.start_as_current_span(
- span_name + " asgi." + scope["type"] + ".send"
- ) as send_span:
- if send_span.is_recording():
- if message["type"] == "http.response.start":
- status_code = message["status"]
- set_status_code(send_span, status_code)
- elif message["type"] == "websocket.send":
- set_status_code(send_span, 200)
- send_span.set_attribute("type", message["type"])
- await send(message)
-
- await self.app(scope, wrapped_receive, wrapped_send)
- finally:
- context.detach(token)
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/version.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py b/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py
deleted file mode 100644
index cf8944ce6df..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py
+++ /dev/null
@@ -1,361 +0,0 @@
-# Copyright The OpenTelemetry 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 sys
-import unittest
-import unittest.mock as mock
-
-import opentelemetry.instrumentation.asgi as otel_asgi
-from opentelemetry import trace as trace_api
-from opentelemetry.test.asgitestutil import (
- AsgiTestBase,
- setup_testing_defaults,
-)
-
-
-async def http_app(scope, receive, send):
- message = await receive()
- assert scope["type"] == "http"
- if message.get("type") == "http.request":
- await send(
- {
- "type": "http.response.start",
- "status": 200,
- "headers": [[b"Content-Type", b"text/plain"]],
- }
- )
- await send({"type": "http.response.body", "body": b"*"})
-
-
-async def websocket_app(scope, receive, send):
- assert scope["type"] == "websocket"
- while True:
- message = await receive()
- if message.get("type") == "websocket.connect":
- await send({"type": "websocket.accept"})
-
- if message.get("type") == "websocket.receive":
- if message.get("text") == "ping":
- await send({"type": "websocket.send", "text": "pong"})
-
- if message.get("type") == "websocket.disconnect":
- break
-
-
-async def simple_asgi(scope, receive, send):
- assert isinstance(scope, dict)
- if scope["type"] == "http":
- await http_app(scope, receive, send)
- elif scope["type"] == "websocket":
- await websocket_app(scope, receive, send)
-
-
-async def error_asgi(scope, receive, send):
- assert isinstance(scope, dict)
- assert scope["type"] == "http"
- message = await receive()
- if message.get("type") == "http.request":
- try:
- raise ValueError
- except ValueError:
- scope["hack_exc_info"] = sys.exc_info()
- await send(
- {
- "type": "http.response.start",
- "status": 200,
- "headers": [[b"Content-Type", b"text/plain"]],
- }
- )
- await send({"type": "http.response.body", "body": b"*"})
-
-
-class TestAsgiApplication(AsgiTestBase):
- def validate_outputs(self, outputs, error=None, modifiers=None):
- # Ensure modifiers is a list
- modifiers = modifiers or []
- # Check for expected outputs
- self.assertEqual(len(outputs), 2)
- response_start = outputs[0]
- response_body = outputs[1]
- self.assertEqual(response_start["type"], "http.response.start")
- self.assertEqual(response_body["type"], "http.response.body")
-
- # Check http response body
- self.assertEqual(response_body["body"], b"*")
-
- # Check http response start
- self.assertEqual(response_start["status"], 200)
- self.assertEqual(
- response_start["headers"], [[b"Content-Type", b"text/plain"]]
- )
-
- exc_info = self.scope.get("hack_exc_info")
- if error:
- self.assertIs(exc_info[0], error)
- self.assertIsInstance(exc_info[1], error)
- self.assertIsNotNone(exc_info[2])
- else:
- self.assertIsNone(exc_info)
-
- # Check spans
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 4)
- expected = [
- {
- "name": "GET asgi.http.receive",
- "kind": trace_api.SpanKind.INTERNAL,
- "attributes": {"type": "http.request"},
- },
- {
- "name": "GET asgi.http.send",
- "kind": trace_api.SpanKind.INTERNAL,
- "attributes": {
- "http.status_code": 200,
- "type": "http.response.start",
- },
- },
- {
- "name": "GET asgi.http.send",
- "kind": trace_api.SpanKind.INTERNAL,
- "attributes": {"type": "http.response.body"},
- },
- {
- "name": "GET asgi",
- "kind": trace_api.SpanKind.SERVER,
- "attributes": {
- "component": "http",
- "http.method": "GET",
- "http.scheme": "http",
- "host.port": 80,
- "http.host": "127.0.0.1",
- "http.flavor": "1.0",
- "http.target": "/",
- "http.url": "http://127.0.0.1/",
- "net.peer.ip": "127.0.0.1",
- "net.peer.port": 32767,
- },
- },
- ]
- # Run our expected modifiers
- for modifier in modifiers:
- expected = modifier(expected)
- # Check that output matches
- for span, expected in zip(span_list, expected):
- self.assertEqual(span.name, expected["name"])
- self.assertEqual(span.kind, expected["kind"])
- self.assertDictEqual(dict(span.attributes), expected["attributes"])
-
- def test_basic_asgi_call(self):
- """Test that spans are emitted as expected."""
- app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
- self.seed_app(app)
- self.send_default_request()
- outputs = self.get_all_output()
- self.validate_outputs(outputs)
-
- def test_wsgi_not_recording(self):
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_as_current_span.return_value = mock_span
- mock_tracer.start_as_current_span.return_value.__enter__ = mock_span
- mock_tracer.start_as_current_span.return_value.__exit__ = mock_span
- with mock.patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
- self.seed_app(app)
- self.send_default_request()
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_asgi_exc_info(self):
- """Test that exception information is emitted as expected."""
- app = otel_asgi.OpenTelemetryMiddleware(error_asgi)
- self.seed_app(app)
- self.send_default_request()
- outputs = self.get_all_output()
- self.validate_outputs(outputs, error=ValueError)
-
- def test_override_span_name(self):
- """Test that span_names can be overwritten by our callback function."""
- span_name = "Dymaxion"
-
- def get_predefined_span_details(_):
- return span_name, {}
-
- def update_expected_span_name(expected):
- for entry in expected:
- entry["name"] = " ".join(
- [span_name] + entry["name"].split(" ")[-1:]
- )
- return expected
-
- app = otel_asgi.OpenTelemetryMiddleware(
- simple_asgi, span_details_callback=get_predefined_span_details
- )
- self.seed_app(app)
- self.send_default_request()
- outputs = self.get_all_output()
- self.validate_outputs(outputs, modifiers=[update_expected_span_name])
-
- def test_behavior_with_scope_server_as_none(self):
- """Test that middleware is ok when server is none in scope."""
-
- def update_expected_server(expected):
- expected[3]["attributes"].update(
- {
- "http.host": "0.0.0.0",
- "host.port": 80,
- "http.url": "http://0.0.0.0/",
- }
- )
- return expected
-
- self.scope["server"] = None
- app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
- self.seed_app(app)
- self.send_default_request()
- outputs = self.get_all_output()
- self.validate_outputs(outputs, modifiers=[update_expected_server])
-
- def test_host_header(self):
- """Test that host header is converted to http.server_name."""
- hostname = b"server_name_1"
-
- def update_expected_server(expected):
- expected[3]["attributes"].update(
- {"http.server_name": hostname.decode("utf8")}
- )
- return expected
-
- self.scope["headers"].append([b"host", hostname])
- app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
- self.seed_app(app)
- self.send_default_request()
- outputs = self.get_all_output()
- self.validate_outputs(outputs, modifiers=[update_expected_server])
-
- def test_user_agent(self):
- """Test that host header is converted to http.server_name."""
- user_agent = b"test-agent"
-
- def update_expected_user_agent(expected):
- expected[3]["attributes"].update(
- {"http.user_agent": user_agent.decode("utf8")}
- )
- return expected
-
- self.scope["headers"].append([b"user-agent", user_agent])
- app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
- self.seed_app(app)
- self.send_default_request()
- outputs = self.get_all_output()
- self.validate_outputs(outputs, modifiers=[update_expected_user_agent])
-
- def test_websocket(self):
- self.scope = {
- "type": "websocket",
- "http_version": "1.1",
- "scheme": "ws",
- "path": "/",
- "query_string": b"",
- "headers": [],
- "client": ("127.0.0.1", 32767),
- "server": ("127.0.0.1", 80),
- }
- app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
- self.seed_app(app)
- self.send_input({"type": "websocket.connect"})
- self.send_input({"type": "websocket.receive", "text": "ping"})
- self.send_input({"type": "websocket.disconnect"})
- self.get_all_output()
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 6)
- expected = [
- "/ asgi.websocket.receive",
- "/ asgi.websocket.send",
- "/ asgi.websocket.receive",
- "/ asgi.websocket.send",
- "/ asgi.websocket.receive",
- "/ asgi",
- ]
- actual = [span.name for span in span_list]
- self.assertListEqual(actual, expected)
-
- def test_lifespan(self):
- self.scope["type"] = "lifespan"
- app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
- self.seed_app(app)
- self.send_default_request()
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 0)
-
-
-class TestAsgiAttributes(unittest.TestCase):
- def setUp(self):
- self.scope = {}
- setup_testing_defaults(self.scope)
- self.span = mock.create_autospec(trace_api.Span, spec_set=True)
-
- def test_request_attributes(self):
- self.scope["query_string"] = b"foo=bar"
-
- attrs = otel_asgi.collect_request_attributes(self.scope)
- self.assertDictEqual(
- attrs,
- {
- "component": "http",
- "http.method": "GET",
- "http.host": "127.0.0.1",
- "http.target": "/",
- "http.url": "http://127.0.0.1/?foo=bar",
- "host.port": 80,
- "http.scheme": "http",
- "http.flavor": "1.0",
- "net.peer.ip": "127.0.0.1",
- "net.peer.port": 32767,
- },
- )
-
- def test_query_string(self):
- self.scope["query_string"] = b"foo=bar"
- attrs = otel_asgi.collect_request_attributes(self.scope)
- self.assertEqual(attrs["http.url"], "http://127.0.0.1/?foo=bar")
-
- def test_query_string_percent_bytes(self):
- self.scope["query_string"] = b"foo%3Dbar"
- attrs = otel_asgi.collect_request_attributes(self.scope)
- self.assertEqual(attrs["http.url"], "http://127.0.0.1/?foo=bar")
-
- def test_query_string_percent_str(self):
- self.scope["query_string"] = "foo%3Dbar"
- attrs = otel_asgi.collect_request_attributes(self.scope)
- self.assertEqual(attrs["http.url"], "http://127.0.0.1/?foo=bar")
-
- def test_response_attributes(self):
- otel_asgi.set_status_code(self.span, 404)
- expected = (mock.call("http.status_code", 404),)
- self.assertEqual(self.span.set_attribute.call_count, 1)
- self.assertEqual(self.span.set_attribute.call_count, 1)
- self.span.set_attribute.assert_has_calls(expected, any_order=True)
-
- def test_response_attributes_invalid_status_code(self):
- otel_asgi.set_status_code(self.span, "Invalid Status Code")
- self.assertEqual(self.span.set_status.call_count, 1)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-asyncpg/CHANGELOG.md
deleted file mode 100644
index 56f261c9b54..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asyncpg/CHANGELOG.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-asyncpg
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## Version 0.11b0
-
-Released 2020-07-28
-
-- Shouldn't capture query parameters by default
- ([#854](https://github.com/open-telemetry/opentelemetry-python/pull/854))
-
-## Version 0.10b0
-
-Released 2020-06-23
-
-- Initial Release ([#814](https://github.com/open-telemetry/opentelemetry-python/pull/814))
diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/README.rst b/instrumentation/opentelemetry-instrumentation-asyncpg/README.rst
deleted file mode 100644
index 33c60852cd4..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asyncpg/README.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-OpenTelemetry asyncpg Instrumentation
-=====================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-asyncpg.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-asyncpg/
-
-This library allows tracing PostgreSQL queries made by the
-`asyncpg `_ library.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-asyncpg
-
-References
-----------
-
-* `OpenTelemetry asyncpg Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/setup.cfg b/instrumentation/opentelemetry-instrumentation-asyncpg/setup.cfg
deleted file mode 100644
index 0e0e32fc8bc..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asyncpg/setup.cfg
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-asyncpg
-description = OpenTelemetry instrumentation for AsyncPG
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/instrumentation/opentelemetry-instrumentation-asyncpg
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- asyncpg >= 0.12.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- asyncpg = opentelemetry.instrumentation.asyncpg:AsyncPGInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/setup.py b/instrumentation/opentelemetry-instrumentation-asyncpg/setup.py
deleted file mode 100644
index 2ad47ac9d98..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asyncpg/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "asyncpg",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py
deleted file mode 100644
index 2f4ecaf3af6..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-This library allows tracing PostgreSQL queries made by the
-`asyncpg `_ library.
-
-Usage
------
-
-.. code-block:: python
-
- import asyncpg
- from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor
-
- # You can optionally pass a custom TracerProvider to AsyncPGInstrumentor.instrument()
- AsyncPGInstrumentor().instrument()
- conn = await asyncpg.connect(user='user', password='password',
- database='database', host='127.0.0.1')
- values = await conn.fetch('''SELECT 42;''')
-
-API
----
-"""
-
-import asyncpg
-import wrapt
-from asyncpg import exceptions
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.asyncpg.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.utils import unwrap
-from opentelemetry.trace import SpanKind
-from opentelemetry.trace.status import Status, StatusCode
-
-_APPLIED = "_opentelemetry_tracer"
-
-
-def _hydrate_span_from_args(connection, query, parameters) -> dict:
- span_attributes = {"db.type": "sql"}
-
- params = getattr(connection, "_params", None)
- span_attributes["db.instance"] = getattr(params, "database", None)
- span_attributes["db.user"] = getattr(params, "user", None)
-
- if query is not None:
- span_attributes["db.statement"] = query
-
- if parameters is not None and len(parameters) > 0:
- span_attributes["db.statement.parameters"] = str(parameters)
-
- return span_attributes
-
-
-class AsyncPGInstrumentor(BaseInstrumentor):
- def __init__(self, capture_parameters=False):
- super().__init__()
- self.capture_parameters = capture_parameters
-
- def _instrument(self, **kwargs):
- tracer_provider = kwargs.get(
- "tracer_provider", trace.get_tracer_provider()
- )
- setattr(
- asyncpg,
- _APPLIED,
- tracer_provider.get_tracer("asyncpg", __version__),
- )
-
- for method in [
- "Connection.execute",
- "Connection.executemany",
- "Connection.fetch",
- "Connection.fetchval",
- "Connection.fetchrow",
- ]:
- wrapt.wrap_function_wrapper(
- "asyncpg.connection", method, self._do_execute
- )
-
- def _uninstrument(self, **__):
- delattr(asyncpg, _APPLIED)
- for method in [
- "execute",
- "executemany",
- "fetch",
- "fetchval",
- "fetchrow",
- ]:
- unwrap(asyncpg.Connection, method)
-
- async def _do_execute(self, func, instance, args, kwargs):
- tracer = getattr(asyncpg, _APPLIED)
-
- exception = None
-
- with tracer.start_as_current_span(
- "postgresql", kind=SpanKind.CLIENT
- ) as span:
- if span.is_recording():
- span_attributes = _hydrate_span_from_args(
- instance,
- args[0],
- args[1:] if self.capture_parameters else None,
- )
- for attribute, value in span_attributes.items():
- span.set_attribute(attribute, value)
-
- try:
- result = await func(*args, **kwargs)
- except Exception as exc: # pylint: disable=W0703
- exception = exc
- raise
- finally:
- if span.is_recording() and exception is not None:
- span.set_status(Status(StatusCode.ERROR))
-
- return result
diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/version.py b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-asyncpg/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py b/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py
deleted file mode 100644
index 33b121ce53a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import asyncpg
-from asyncpg import Connection
-
-from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor
-from opentelemetry.test.test_base import TestBase
-
-
-class TestAsyncPGInstrumentation(TestBase):
- def test_instrumentation_flags(self):
- AsyncPGInstrumentor().instrument()
- self.assertTrue(hasattr(asyncpg, "_opentelemetry_tracer"))
- AsyncPGInstrumentor().uninstrument()
- self.assertFalse(hasattr(asyncpg, "_opentelemetry_tracer"))
-
- def test_duplicated_instrumentation(self):
- AsyncPGInstrumentor().instrument()
- AsyncPGInstrumentor().instrument()
- AsyncPGInstrumentor().instrument()
- AsyncPGInstrumentor().uninstrument()
- for method_name in ["execute", "fetch"]:
- method = getattr(Connection, method_name, None)
- self.assertFalse(
- hasattr(method, "_opentelemetry_ext_asyncpg_applied")
- )
-
- def test_duplicated_uninstrumentation(self):
- AsyncPGInstrumentor().instrument()
- AsyncPGInstrumentor().uninstrument()
- AsyncPGInstrumentor().uninstrument()
- AsyncPGInstrumentor().uninstrument()
- for method_name in ["execute", "fetch"]:
- method = getattr(Connection, method_name, None)
- self.assertFalse(
- hasattr(method, "_opentelemetry_ext_asyncpg_applied")
- )
diff --git a/instrumentation/opentelemetry-instrumentation-boto/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-boto/CHANGELOG.md
deleted file mode 100644
index ea74ff9de27..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/CHANGELOG.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-boto
- ([#969](https://github.com/open-telemetry/opentelemetry-python/pull/969))
-
-## Version 0.11b0
-
-Released 2020-07-28
-
-- ext/boto and ext/botocore: fails to export spans via jaeger
-([#866](https://github.com/open-telemetry/opentelemetry-python/pull/866))
-
-## 0.9b0
-
-Released 2020-06-10
-
-- Initial release
-
diff --git a/instrumentation/opentelemetry-instrumentation-boto/LICENSE b/instrumentation/opentelemetry-instrumentation-boto/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-boto/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-boto/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-boto/README.rst b/instrumentation/opentelemetry-instrumentation-boto/README.rst
deleted file mode 100644
index 2b40321c006..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/README.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-OpenTelemetry Boto Tracing
-==========================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-boto.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-boto/
-
-This library allows tracing requests made by the Boto library.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-boto
-
-
-References
-----------
-
-* `OpenTelemetry Boto Tracing `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-boto/setup.cfg b/instrumentation/opentelemetry-instrumentation-boto/setup.cfg
deleted file mode 100644
index fadbac4c5cb..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/setup.cfg
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-boto
-description = OpenTelemetry Boto instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-boto
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- boto ~= 2.0
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- opentelemetry-instrumentation-botocore == 0.16.dev0
-
-[options.extras_require]
-test =
- boto~=2.0
- moto~=1.0
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- boto = opentelemetry.instrumentation.boto:BotoInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-boto/setup.py b/instrumentation/opentelemetry-instrumentation-boto/setup.py
deleted file mode 100644
index 2bd68894f33..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "boto", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py b/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py
deleted file mode 100644
index 3bef955d148..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# Copyright The OpenTelemetry 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.
-"""
-Instrument `Boto`_ to trace service requests.
-
-There are two options for instrumenting code. The first option is to use the
-``opentelemetry-instrument`` executable which will automatically
-instrument your Boto client. The second is to programmatically enable
-instrumentation via the following code:
-
-.. _boto: https://pypi.org/project/boto/
-
-Usage
------
-
-.. code:: python
-
- from opentelemetry import trace
- from opentelemetry.instrumentation.boto import BotoInstrumentor
- from opentelemetry.sdk.trace import TracerProvider
- import boto
-
- trace.set_tracer_provider(TracerProvider())
-
- # Instrument Boto
- BotoInstrumentor().instrument(tracer_provider=trace.get_tracer_provider())
-
- # This will create a span with Boto-specific attributes
- ec2 = boto.ec2.connect_to_region("us-west-2")
- ec2.get_all_instances()
-
-API
----
-"""
-
-import logging
-from inspect import currentframe
-
-from boto.connection import AWSAuthConnection, AWSQueryConnection
-from wrapt import wrap_function_wrapper
-
-from opentelemetry.instrumentation.boto.version import __version__
-from opentelemetry.instrumentation.botocore import add_span_arg_tags, unwrap
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.sdk.trace import Resource
-from opentelemetry.trace import SpanKind, get_tracer
-
-logger = logging.getLogger(__name__)
-
-
-def _get_instance_region_name(instance):
- region = getattr(instance, "region", None)
-
- if not region:
- return None
- if isinstance(region, str):
- return region.split(":")[1]
- return region.name
-
-
-class BotoInstrumentor(BaseInstrumentor):
- """A instrumentor for Boto
-
- See `BaseInstrumentor`
- """
-
- def __init__(self):
- super().__init__()
- self._original_boto = None
-
- def _instrument(self, **kwargs):
- # AWSQueryConnection and AWSAuthConnection are two different classes
- # called by different services for connection.
- # For exemple EC2 uses AWSQueryConnection and S3 uses
- # AWSAuthConnection
-
- # FIXME should the tracer provider be accessed via Configuration
- # instead?
- # pylint: disable=attribute-defined-outside-init
- self._tracer = get_tracer(
- __name__, __version__, kwargs.get("tracer_provider")
- )
-
- wrap_function_wrapper(
- "boto.connection",
- "AWSQueryConnection.make_request",
- self._patched_query_request,
- )
- wrap_function_wrapper(
- "boto.connection",
- "AWSAuthConnection.make_request",
- self._patched_auth_request,
- )
-
- def _uninstrument(self, **kwargs):
- unwrap(AWSQueryConnection, "make_request")
- unwrap(AWSAuthConnection, "make_request")
-
- def _common_request( # pylint: disable=too-many-locals
- self,
- args_name,
- traced_args,
- operation_name,
- original_func,
- instance,
- args,
- kwargs,
- ):
-
- endpoint_name = getattr(instance, "host").split(".")[0]
-
- with self._tracer.start_as_current_span(
- "{}.command".format(endpoint_name), kind=SpanKind.CONSUMER,
- ) as span:
- if args:
- http_method = args[0]
- span.resource = Resource(
- attributes={
- "endpoint": endpoint_name,
- "http_method": http_method.lower(),
- }
- )
- else:
- span.resource = Resource(
- attributes={"endpoint": endpoint_name}
- )
-
- # Original func returns a boto.connection.HTTPResponse object
- result = original_func(*args, **kwargs)
-
- if span.is_recording():
- add_span_arg_tags(
- span, endpoint_name, args, args_name, traced_args,
- )
-
- # Obtaining region name
- region_name = _get_instance_region_name(instance)
-
- meta = {
- "aws.agent": "boto",
- "aws.operation": operation_name,
- }
- if region_name:
- meta["aws.region"] = region_name
-
- for key, value in meta.items():
- span.set_attribute(key, value)
-
- span.set_attribute(
- "http.status_code", getattr(result, "status")
- )
- span.set_attribute("http.method", getattr(result, "_method"))
-
- return result
-
- def _patched_query_request(self, original_func, instance, args, kwargs):
-
- return self._common_request(
- ("operation_name", "params", "path", "verb"),
- ["operation_name", "params", "path"],
- args[0] if args else None,
- original_func,
- instance,
- args,
- kwargs,
- )
-
- def _patched_auth_request(self, original_func, instance, args, kwargs):
- operation_name = None
-
- frame = currentframe().f_back
- operation_name = None
- while frame:
- if frame.f_code.co_name == "make_request":
- operation_name = frame.f_back.f_code.co_name
- break
- frame = frame.f_back
-
- return self._common_request(
- (
- "method",
- "path",
- "headers",
- "data",
- "host",
- "auth_path",
- "sender",
- ),
- ["path", "data", "host"],
- operation_name,
- original_func,
- instance,
- args,
- kwargs,
- )
diff --git a/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/version.py b/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-boto/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-boto/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-boto/tests/conftest.py b/instrumentation/opentelemetry-instrumentation-boto/tests/conftest.py
deleted file mode 100644
index 884c6753c16..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/tests/conftest.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os import environ
-
-
-def pytest_sessionstart(session):
- # pylint: disable=unused-argument
- environ["AWS_ACCESS_KEY_ID"] = "testing"
- environ["AWS_SECRET_ACCESS_KEY"] = "testing"
- environ["AWS_SECURITY_TOKEN"] = "testing"
- environ["AWS_SESSION_TOKEN"] = "testing"
-
-
-def pytest_sessionfinish(session):
- # pylint: disable=unused-argument
- environ.pop("AWS_ACCESS_KEY_ID")
- environ.pop("AWS_SECRET_ACCESS_KEY")
- environ.pop("AWS_SECURITY_TOKEN")
- environ.pop("AWS_SESSION_TOKEN")
diff --git a/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py b/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py
deleted file mode 100644
index cb45514c799..00000000000
--- a/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py
+++ /dev/null
@@ -1,294 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest import skipUnless
-from unittest.mock import Mock, patch
-
-import boto.awslambda
-import boto.ec2
-import boto.elasticache
-import boto.s3
-import boto.sts
-from moto import ( # pylint: disable=import-error
- mock_ec2_deprecated,
- mock_lambda_deprecated,
- mock_s3_deprecated,
- mock_sts_deprecated,
-)
-
-from opentelemetry.instrumentation.boto import BotoInstrumentor
-from opentelemetry.sdk.resources import Resource
-from opentelemetry.test.test_base import TestBase
-
-
-def assert_span_http_status_code(span, code):
- """Assert on the span's 'http.status_code' tag"""
- tag = span.attributes["http.status_code"]
- assert tag == code, "%r != %r" % (tag, code)
-
-
-class TestBotoInstrumentor(TestBase):
- """Botocore integration testsuite"""
-
- def setUp(self):
- super().setUp()
- BotoInstrumentor().instrument()
-
- def tearDown(self):
- BotoInstrumentor().uninstrument()
-
- @mock_ec2_deprecated
- def test_ec2_client(self):
- ec2 = boto.ec2.connect_to_region("us-west-2")
-
- ec2.get_all_instances()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self.assertEqual(span.attributes["aws.operation"], "DescribeInstances")
- assert_span_http_status_code(span, 200)
- self.assertEqual(span.attributes["http.method"], "POST")
- self.assertEqual(span.attributes["aws.region"], "us-west-2")
-
- # Create an instance
- ec2.run_instances(21)
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- self.assertEqual(len(spans), 2)
- span = spans[1]
- self.assertEqual(span.attributes["aws.operation"], "RunInstances")
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(
- attributes={"endpoint": "ec2", "http_method": "runinstances"}
- ),
- )
- self.assertEqual(span.attributes["http.method"], "POST")
- self.assertEqual(span.attributes["aws.region"], "us-west-2")
- self.assertEqual(span.name, "ec2.command")
-
- @mock_ec2_deprecated
- def test_not_recording(self):
- mock_tracer = Mock()
- mock_span = Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- with patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- ec2 = boto.ec2.connect_to_region("us-west-2")
- ec2.get_all_instances()
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- @mock_ec2_deprecated
- def test_analytics_enabled_with_rate(self):
- ec2 = boto.ec2.connect_to_region("us-west-2")
-
- ec2.get_all_instances()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
-
- @mock_ec2_deprecated
- def test_analytics_enabled_without_rate(self):
- ec2 = boto.ec2.connect_to_region("us-west-2")
-
- ec2.get_all_instances()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
-
- @mock_s3_deprecated
- def test_s3_client(self):
- s3 = boto.s3.connect_to_region("us-east-1")
-
- s3.get_all_buckets()
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- self.assertEqual(len(spans), 1)
- span = spans[0]
- assert_span_http_status_code(span, 200)
- self.assertEqual(span.attributes["http.method"], "GET")
- self.assertEqual(span.attributes["aws.operation"], "get_all_buckets")
-
- # Create a bucket command
- s3.create_bucket("cheese")
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- self.assertEqual(len(spans), 2)
- span = spans[1]
- assert_span_http_status_code(span, 200)
- self.assertEqual(span.attributes["http.method"], "PUT")
- self.assertEqual(span.attributes["path"], "/")
- self.assertEqual(span.attributes["aws.operation"], "create_bucket")
-
- # Get the created bucket
- s3.get_bucket("cheese")
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- self.assertEqual(len(spans), 3)
- span = spans[2]
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(attributes={"endpoint": "s3", "http_method": "head"}),
- )
- self.assertEqual(span.attributes["http.method"], "HEAD")
- self.assertEqual(span.attributes["aws.operation"], "head_bucket")
- self.assertEqual(span.name, "s3.command")
-
- # Checking for resource incase of error
- try:
- s3.get_bucket("big_bucket")
- except Exception: # pylint: disable=broad-except
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[2]
- self.assertEqual(
- span.resource,
- Resource(attributes={"endpoint": "s3", "http_method": "head"}),
- )
-
- @mock_s3_deprecated
- def test_s3_put(self):
- s3 = boto.s3.connect_to_region("us-east-1")
- s3.create_bucket("mybucket")
- bucket = s3.get_bucket("mybucket")
- key = boto.s3.key.Key(bucket)
- key.key = "foo"
- key.set_contents_from_string("bar")
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- # create bucket
- self.assertEqual(len(spans), 3)
- self.assertEqual(spans[0].attributes["aws.operation"], "create_bucket")
- assert_span_http_status_code(spans[0], 200)
- self.assertEqual(
- spans[0].resource,
- Resource(attributes={"endpoint": "s3", "http_method": "put"}),
- )
- # get bucket
- self.assertEqual(spans[1].attributes["aws.operation"], "head_bucket")
- self.assertEqual(
- spans[1].resource,
- Resource(attributes={"endpoint": "s3", "http_method": "head"}),
- )
- # put object
- self.assertEqual(
- spans[2].attributes["aws.operation"], "_send_file_internal"
- )
- self.assertEqual(
- spans[2].resource,
- Resource(attributes={"endpoint": "s3", "http_method": "put"}),
- )
-
- @mock_lambda_deprecated
- def test_unpatch(self):
-
- lamb = boto.awslambda.connect_to_region("us-east-2")
-
- BotoInstrumentor().uninstrument()
-
- # multiple calls
- lamb.list_functions()
- spans = self.memory_exporter.get_finished_spans()
- assert not spans, spans
-
- @mock_s3_deprecated
- def test_double_patch(self):
- s3 = boto.s3.connect_to_region("us-east-1")
-
- BotoInstrumentor().instrument()
- BotoInstrumentor().instrument()
-
- # Get the created bucket
- s3.create_bucket("cheese")
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- self.assertEqual(len(spans), 1)
-
- @mock_lambda_deprecated
- def test_lambda_client(self):
- lamb = boto.awslambda.connect_to_region("us-east-2")
-
- # multiple calls
- lamb.list_functions()
- lamb.list_functions()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- self.assertEqual(len(spans), 2)
- span = spans[0]
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(attributes={"endpoint": "lambda", "http_method": "get"}),
- )
- self.assertEqual(span.attributes["http.method"], "GET")
- self.assertEqual(span.attributes["aws.region"], "us-east-2")
- self.assertEqual(span.attributes["aws.operation"], "list_functions")
-
- @mock_sts_deprecated
- def test_sts_client(self):
- sts = boto.sts.connect_to_region("us-west-2")
-
- sts.get_federation_token(12, duration=10)
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[0]
- self.assertEqual(
- span.resource,
- Resource(
- attributes={
- "endpoint": "sts",
- "http_method": "getfederationtoken",
- }
- ),
- )
- self.assertEqual(span.attributes["aws.region"], "us-west-2")
- self.assertEqual(
- span.attributes["aws.operation"], "GetFederationToken"
- )
-
- # checking for protection on sts against security leak
- self.assertTrue("args.path" not in span.attributes.keys())
-
- @skipUnless(
- False,
- (
- "Test to reproduce the case where args sent to patched function "
- "are None, can't be mocked: needs AWS credentials"
- ),
- )
- def test_elasticache_client(self):
- elasticache = boto.elasticache.connect_to_region("us-west-2")
-
- elasticache.describe_cache_clusters()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[0]
- self.assertEqual(
- span.resource, Resource(attributes={"endpoint": "elasticcache"})
- )
- self.assertEqual(span.attributes["aws.region"], "us-west-2")
diff --git a/instrumentation/opentelemetry-instrumentation-botocore/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-botocore/CHANGELOG.md
deleted file mode 100644
index 9a01165b8f5..00000000000
--- a/instrumentation/opentelemetry-instrumentation-botocore/CHANGELOG.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-botocore
- ([#969](https://github.com/open-telemetry/opentelemetry-python/pull/969))
-
-## Version 0.11b0
-
-Released 2020-07-28
-
-- ext/boto and ext/botocore: fails to export spans via jaeger
-([#866](https://github.com/open-telemetry/opentelemetry-python/pull/866))
-
-## 0.9b0
-
-Released 2020-06-10
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-botocore/LICENSE b/instrumentation/opentelemetry-instrumentation-botocore/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-botocore/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-botocore/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-botocore/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-botocore/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-botocore/README.rst b/instrumentation/opentelemetry-instrumentation-botocore/README.rst
deleted file mode 100644
index 4f5eb9d9aff..00000000000
--- a/instrumentation/opentelemetry-instrumentation-botocore/README.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-OpenTelemetry Botocore Tracing
-==============================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-botocore.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-botocore/
-
-This library allows tracing requests made by the Botocore library.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-botocore
-
-
-References
-----------
-
-* `OpenTelemetry Botocore Tracing `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-botocore/setup.cfg b/instrumentation/opentelemetry-instrumentation-botocore/setup.cfg
deleted file mode 100644
index 6bd0190ac20..00000000000
--- a/instrumentation/opentelemetry-instrumentation-botocore/setup.cfg
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-botocore
-description = OpenTelemetry Botocore instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-botocore
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- botocore ~= 1.0
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
-
-[options.extras_require]
-test =
- moto ~= 1.0
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- botocore = opentelemetry.instrumentation.botocore:BotocoreInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-botocore/setup.py b/instrumentation/opentelemetry-instrumentation-botocore/setup.py
deleted file mode 100644
index fd5045efaa6..00000000000
--- a/instrumentation/opentelemetry-instrumentation-botocore/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "botocore",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py
deleted file mode 100644
index b574b86cfb2..00000000000
--- a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py
+++ /dev/null
@@ -1,222 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-Instrument `Botocore`_ to trace service requests.
-
-There are two options for instrumenting code. The first option is to use the
-``opentelemetry-instrument`` executable which will automatically
-instrument your Botocore client. The second is to programmatically enable
-instrumentation via the following code:
-
-.. _Botocore: https://pypi.org/project/botocore/
-
-Usage
------
-
-.. code:: python
-
- from opentelemetry import trace
- from opentelemetry.instrumentation.botocore import BotocoreInstrumentor
- from opentelemetry.sdk.trace import TracerProvider
- import botocore
-
- trace.set_tracer_provider(TracerProvider())
-
- # Instrument Botocore
- BotocoreInstrumentor().instrument(
- tracer_provider=trace.get_tracer_provider()
- )
-
- # This will create a span with Botocore-specific attributes
- session = botocore.session.get_session()
- session.set_credentials(
- access_key="access-key", secret_key="secret-key"
- )
- ec2 = self.session.create_client("ec2", region_name="us-west-2")
- ec2.describe_instances()
-
-API
----
-"""
-
-import logging
-
-from botocore.client import BaseClient
-from wrapt import ObjectProxy, wrap_function_wrapper
-
-from opentelemetry.instrumentation.botocore.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.sdk.trace import Resource
-from opentelemetry.trace import SpanKind, get_tracer
-
-logger = logging.getLogger(__name__)
-
-
-class BotocoreInstrumentor(BaseInstrumentor):
- """A instrumentor for Botocore
-
- See `BaseInstrumentor`
- """
-
- def _instrument(self, **kwargs):
-
- # FIXME should the tracer provider be accessed via Configuration
- # instead?
- # pylint: disable=attribute-defined-outside-init
- self._tracer = get_tracer(
- __name__, __version__, kwargs.get("tracer_provider")
- )
-
- wrap_function_wrapper(
- "botocore.client",
- "BaseClient._make_api_call",
- self._patched_api_call,
- )
-
- def _uninstrument(self, **kwargs):
- unwrap(BaseClient, "_make_api_call")
-
- def _patched_api_call(self, original_func, instance, args, kwargs):
-
- endpoint_name = deep_getattr(instance, "_endpoint._endpoint_prefix")
-
- with self._tracer.start_as_current_span(
- "{}.command".format(endpoint_name), kind=SpanKind.CONSUMER,
- ) as span:
-
- operation = None
- if args and span.is_recording():
- operation = args[0]
- span.resource = Resource(
- attributes={
- "endpoint": endpoint_name,
- "operation": operation.lower(),
- }
- )
-
- else:
- span.resource = Resource(
- attributes={"endpoint": endpoint_name}
- )
-
- add_span_arg_tags(
- span,
- endpoint_name,
- args,
- ("action", "params", "path", "verb"),
- {"params", "path", "verb"},
- )
-
- if span.is_recording():
- region_name = deep_getattr(instance, "meta.region_name")
-
- meta = {
- "aws.agent": "botocore",
- "aws.operation": operation,
- "aws.region": region_name,
- }
- for key, value in meta.items():
- span.set_attribute(key, value)
-
- result = original_func(*args, **kwargs)
-
- if span.is_recording():
- span.set_attribute(
- "http.status_code",
- result["ResponseMetadata"]["HTTPStatusCode"],
- )
- span.set_attribute(
- "retry_attempts",
- result["ResponseMetadata"]["RetryAttempts"],
- )
-
- return result
-
-
-def unwrap(obj, attr):
- function = getattr(obj, attr, None)
- if (
- function
- and isinstance(function, ObjectProxy)
- and hasattr(function, "__wrapped__")
- ):
- setattr(obj, attr, function.__wrapped__)
-
-
-def add_span_arg_tags(span, endpoint_name, args, args_names, args_traced):
- def truncate_arg_value(value, max_len=1024):
- """Truncate values which are bytes and greater than `max_len`.
- Useful for parameters like "Body" in `put_object` operations.
- """
- if isinstance(value, bytes) and len(value) > max_len:
- return b"..."
-
- return value
-
- def flatten_dict(dict_, sep=".", prefix=""):
- """
- Returns a normalized dict of depth 1 with keys in order of embedding
- """
- # adapted from https://stackoverflow.com/a/19647596
- return (
- {
- prefix + sep + k if prefix else k: v
- for kk, vv in dict_.items()
- for k, v in flatten_dict(vv, sep, kk).items()
- }
- if isinstance(dict_, dict)
- else {prefix: dict_}
- )
-
- if not span.is_recording():
- return
-
- if endpoint_name not in {"kms", "sts"}:
- tags = dict(
- (name, value)
- for (name, value) in zip(args_names, args)
- if name in args_traced
- )
- tags = flatten_dict(tags)
- for key, value in {
- k: truncate_arg_value(v)
- for k, v in tags.items()
- if k not in {"s3": ["params.Body"]}.get(endpoint_name, [])
- }.items():
- span.set_attribute(key, value)
-
-
-def deep_getattr(obj, attr_string, default=None):
- """
- Returns the attribute of ``obj`` at the dotted path given by
- ``attr_string``, if no such attribute is reachable, returns ``default``.
-
- >>> deep_getattr(cass, "cluster")
- >> deep_getattr(cass, "cluster.metadata.partitioner")
- u"org.apache.cassandra.dht.Murmur3Partitioner"
-
- >>> deep_getattr(cass, "i.dont.exist", default="default")
- "default"
- """
- attrs = attr_string.split(".")
- for attr in attrs:
- try:
- obj = getattr(obj, attr)
- except AttributeError:
- return default
-
- return obj
diff --git a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/version.py b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-botocore/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-botocore/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py b/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py
deleted file mode 100644
index fba0182eec4..00000000000
--- a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py
+++ /dev/null
@@ -1,277 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest.mock import Mock, patch
-
-import botocore.session
-from botocore.exceptions import ParamValidationError
-from moto import ( # pylint: disable=import-error
- mock_ec2,
- mock_kinesis,
- mock_kms,
- mock_lambda,
- mock_s3,
- mock_sqs,
-)
-
-from opentelemetry.instrumentation.botocore import BotocoreInstrumentor
-from opentelemetry.sdk.resources import Resource
-from opentelemetry.test.test_base import TestBase
-
-
-def assert_span_http_status_code(span, code):
- """Assert on the span"s "http.status_code" tag"""
- tag = span.attributes["http.status_code"]
- assert tag == code, "%r != %r" % (tag, code)
-
-
-class TestBotocoreInstrumentor(TestBase):
- """Botocore integration testsuite"""
-
- def setUp(self):
- super().setUp()
- BotocoreInstrumentor().instrument()
-
- self.session = botocore.session.get_session()
- self.session.set_credentials(
- access_key="access-key", secret_key="secret-key"
- )
-
- def tearDown(self):
- super().tearDown()
- BotocoreInstrumentor().uninstrument()
-
- @mock_ec2
- def test_traced_client(self):
- ec2 = self.session.create_client("ec2", region_name="us-west-2")
-
- ec2.describe_instances()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[0]
- self.assertEqual(len(spans), 1)
- self.assertEqual(span.attributes["aws.agent"], "botocore")
- self.assertEqual(span.attributes["aws.region"], "us-west-2")
- self.assertEqual(span.attributes["aws.operation"], "DescribeInstances")
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(
- attributes={
- "endpoint": "ec2",
- "operation": "describeinstances",
- }
- ),
- )
- self.assertEqual(span.name, "ec2.command")
-
- @mock_ec2
- def test_not_recording(self):
- mock_tracer = Mock()
- mock_span = Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- with patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- ec2 = self.session.create_client("ec2", region_name="us-west-2")
- ec2.describe_instances()
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- @mock_ec2
- def test_traced_client_analytics(self):
- ec2 = self.session.create_client("ec2", region_name="us-west-2")
- ec2.describe_instances()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
-
- @mock_s3
- def test_s3_client(self):
- s3 = self.session.create_client("s3", region_name="us-west-2")
-
- s3.list_buckets()
- s3.list_buckets()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[0]
- self.assertEqual(len(spans), 2)
- self.assertEqual(span.attributes["aws.operation"], "ListBuckets")
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(
- attributes={"endpoint": "s3", "operation": "listbuckets"}
- ),
- )
-
- # testing for span error
- self.memory_exporter.get_finished_spans()
- with self.assertRaises(ParamValidationError):
- s3.list_objects(bucket="mybucket")
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[2]
- self.assertEqual(
- span.resource,
- Resource(
- attributes={"endpoint": "s3", "operation": "listobjects"}
- ),
- )
-
- # Comment test for issue 1088
- @mock_s3
- def test_s3_put(self):
- params = dict(Key="foo", Bucket="mybucket", Body=b"bar")
- s3 = self.session.create_client("s3", region_name="us-west-2")
- location = {"LocationConstraint": "us-west-2"}
- s3.create_bucket(Bucket="mybucket", CreateBucketConfiguration=location)
- s3.put_object(**params)
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[0]
- self.assertEqual(len(spans), 2)
- self.assertEqual(span.attributes["aws.operation"], "CreateBucket")
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(
- attributes={"endpoint": "s3", "operation": "createbucket"}
- ),
- )
- self.assertEqual(spans[1].attributes["aws.operation"], "PutObject")
- self.assertEqual(
- spans[1].resource,
- Resource(attributes={"endpoint": "s3", "operation": "putobject"}),
- )
- self.assertEqual(spans[1].attributes["params.Key"], str(params["Key"]))
- self.assertEqual(
- spans[1].attributes["params.Bucket"], str(params["Bucket"])
- )
- self.assertTrue("params.Body" not in spans[1].attributes.keys())
-
- @mock_sqs
- def test_sqs_client(self):
- sqs = self.session.create_client("sqs", region_name="us-east-1")
-
- sqs.list_queues()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[0]
- self.assertEqual(len(spans), 1)
- self.assertEqual(span.attributes["aws.region"], "us-east-1")
- self.assertEqual(span.attributes["aws.operation"], "ListQueues")
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(
- attributes={"endpoint": "sqs", "operation": "listqueues"}
- ),
- )
-
- @mock_kinesis
- def test_kinesis_client(self):
- kinesis = self.session.create_client(
- "kinesis", region_name="us-east-1"
- )
-
- kinesis.list_streams()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[0]
- self.assertEqual(len(spans), 1)
- self.assertEqual(span.attributes["aws.region"], "us-east-1")
- self.assertEqual(span.attributes["aws.operation"], "ListStreams")
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(
- attributes={"endpoint": "kinesis", "operation": "liststreams"}
- ),
- )
-
- @mock_kinesis
- def test_unpatch(self):
- kinesis = self.session.create_client(
- "kinesis", region_name="us-east-1"
- )
-
- BotocoreInstrumentor().uninstrument()
-
- kinesis.list_streams()
- spans = self.memory_exporter.get_finished_spans()
- assert not spans, spans
-
- @mock_sqs
- def test_double_patch(self):
- sqs = self.session.create_client("sqs", region_name="us-east-1")
-
- BotocoreInstrumentor().instrument()
- BotocoreInstrumentor().instrument()
-
- sqs.list_queues()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- self.assertEqual(len(spans), 1)
-
- @mock_lambda
- def test_lambda_client(self):
- lamb = self.session.create_client("lambda", region_name="us-east-1")
-
- lamb.list_functions()
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[0]
- self.assertEqual(len(spans), 1)
- self.assertEqual(span.attributes["aws.region"], "us-east-1")
- self.assertEqual(span.attributes["aws.operation"], "ListFunctions")
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(
- attributes={"endpoint": "lambda", "operation": "listfunctions"}
- ),
- )
-
- @mock_kms
- def test_kms_client(self):
- kms = self.session.create_client("kms", region_name="us-east-1")
-
- kms.list_keys(Limit=21)
-
- spans = self.memory_exporter.get_finished_spans()
- assert spans
- span = spans[0]
- self.assertEqual(len(spans), 1)
- self.assertEqual(span.attributes["aws.region"], "us-east-1")
- self.assertEqual(span.attributes["aws.operation"], "ListKeys")
- assert_span_http_status_code(span, 200)
- self.assertEqual(
- span.resource,
- Resource(attributes={"endpoint": "kms", "operation": "listkeys"}),
- )
-
- # checking for protection on sts against security leak
- self.assertTrue("params" not in span.attributes.keys())
diff --git a/instrumentation/opentelemetry-instrumentation-celery/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-celery/CHANGELOG.md
deleted file mode 100644
index 8ebb8c3d240..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/CHANGELOG.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.14b0
-
-Released 2020-10-13
-
-- Span operation names now include the task type. ([#1135](https://github.com/open-telemetry/opentelemetry-python/pull/1135))
-- Added automatic context propagation. ([#1135](https://github.com/open-telemetry/opentelemetry-python/pull/1135))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-celery
- ([#969](https://github.com/open-telemetry/opentelemetry-python/pull/969))
-
-## Version 0.10b0
-
-Released 2020-06-23
-
-- Add instrumentation for Celery ([#780](https://github.com/open-telemetry/opentelemetry-python/pull/780))
diff --git a/instrumentation/opentelemetry-instrumentation-celery/LICENSE b/instrumentation/opentelemetry-instrumentation-celery/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-celery/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-celery/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-celery/README.rst b/instrumentation/opentelemetry-instrumentation-celery/README.rst
deleted file mode 100644
index 92e5a770a0a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/README.rst
+++ /dev/null
@@ -1,68 +0,0 @@
-OpenTelemetry Celery Instrumentation
-====================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-celery.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-celery/
-
-Instrumentation for Celery.
-
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-celery
-
-Usage
------
-
-* Start broker backend
-
-::
- docker run -p 5672:5672 rabbitmq
-
-
-* Run instrumented task
-
-.. code-block:: python
-
- from opentelemetry import trace
- from opentelemetry.sdk.trace import TracerProvider
- from opentelemetry.sdk.trace.export import BatchExportSpanProcessor
- from opentelemetry.instrumentation.celery import CeleryInstrumentor
-
- from celery import Celery
- from celery.signals import worker_process_init
-
- @worker_process_init.connect(weak=False)
- def init_celery_tracing(*args, **kwargs):
- trace.set_tracer_provider(TracerProvider())
- span_processor = BatchExportSpanProcessor(ConsoleSpanExporter())
- trace.get_tracer_provider().add_span_processor(span_processor)
- CeleryInstrumentor().instrument()
-
- app = Celery("tasks", broker="amqp://localhost")
-
- @app.task
- def add(x, y):
- return x + y
-
- add.delay(42, 50)
-
-
-Setting up tracing
---------------------
-
-When tracing a celery worker process, tracing and instrumention both must be initialized after the celery worker
-process is initialized. This is required for any tracing components that might use threading to work correctly
-such as the BatchExportSpanProcessor. Celery provides a signal called ``worker_process_init`` that can be used to
-accomplish this as shown in the example above.
-
-References
-----------
-* `OpenTelemetry Celery Instrumentation `_
-* `OpenTelemetry Project `_
-
diff --git a/instrumentation/opentelemetry-instrumentation-celery/setup.cfg b/instrumentation/opentelemetry-instrumentation-celery/setup.cfg
deleted file mode 100644
index d1f8866a95d..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/setup.cfg
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-celery
-description = OpenTelemetry Celery Instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-celery
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- celery ~= 4.0
-
-[options.extras_require]
-test =
- pytest
- celery ~= 4.0
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- celery = opentelemetry.instrumentation.celery:CeleryInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-celery/setup.py b/instrumentation/opentelemetry-instrumentation-celery/setup.py
deleted file mode 100644
index ca679306607..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "celery", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py
deleted file mode 100644
index d225e6bd069..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py
+++ /dev/null
@@ -1,262 +0,0 @@
-# Copyright The OpenTelemetry 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.
-"""
-Instrument `celery`_ to trace Celery applications.
-
-.. _celery: https://pypi.org/project/celery/
-
-Usage
------
-
-* Start broker backend
-
-.. code::
-
- docker run -p 5672:5672 rabbitmq
-
-
-* Run instrumented task
-
-.. code:: python
-
- from opentelemetry import trace
- from opentelemetry.sdk.trace import TracerProvider
- from opentelemetry.sdk.trace.export import BatchExportSpanProcessor
- from opentelemetry.instrumentation.celery import CeleryInstrumentor
-
- from celery import Celery
- from celery.signals import worker_process_init
-
- @worker_process_init.connect(weak=False)
- def init_celery_tracing(*args, **kwargs):
- trace.set_tracer_provider(TracerProvider())
- span_processor = BatchExportSpanProcessor(ConsoleSpanExporter())
- trace.get_tracer_provider().add_span_processor(span_processor)
- CeleryInstrumentor().instrument()
-
- app = Celery("tasks", broker="amqp://localhost")
-
- @app.task
- def add(x, y):
- return x + y
-
- add.delay(42, 50)
-
-API
----
-"""
-
-import logging
-import signal
-from collections.abc import Iterable
-
-from celery import signals # pylint: disable=no-name-in-module
-
-from opentelemetry import propagators, trace
-from opentelemetry.instrumentation.celery import utils
-from opentelemetry.instrumentation.celery.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.trace.propagation.textmap import DictGetter
-from opentelemetry.trace.status import Status, StatusCode
-
-logger = logging.getLogger(__name__)
-
-# Task operations
-_TASK_TAG_KEY = "celery.action"
-_TASK_APPLY_ASYNC = "apply_async"
-_TASK_RUN = "run"
-
-_TASK_RETRY_REASON_KEY = "celery.retry.reason"
-_TASK_REVOKED_REASON_KEY = "celery.revoked.reason"
-_TASK_REVOKED_TERMINATED_SIGNAL_KEY = "celery.terminated.signal"
-_TASK_NAME_KEY = "celery.task_name"
-_MESSAGE_ID_ATTRIBUTE_NAME = "messaging.message_id"
-
-
-class CarrierGetter(DictGetter):
- def get(self, carrier, key):
- value = getattr(carrier, key, [])
- if isinstance(value, str) or not isinstance(value, Iterable):
- value = (value,)
- return value
-
- def keys(self, carrier):
- return []
-
-
-carrier_getter = CarrierGetter()
-
-
-class CeleryInstrumentor(BaseInstrumentor):
- def _instrument(self, **kwargs):
- tracer_provider = kwargs.get("tracer_provider")
-
- # pylint: disable=attribute-defined-outside-init
- self._tracer = trace.get_tracer(__name__, __version__, tracer_provider)
-
- signals.task_prerun.connect(self._trace_prerun, weak=False)
- signals.task_postrun.connect(self._trace_postrun, weak=False)
- signals.before_task_publish.connect(
- self._trace_before_publish, weak=False
- )
- signals.after_task_publish.connect(
- self._trace_after_publish, weak=False
- )
- signals.task_failure.connect(self._trace_failure, weak=False)
- signals.task_retry.connect(self._trace_retry, weak=False)
-
- def _uninstrument(self, **kwargs):
- signals.task_prerun.disconnect(self._trace_prerun)
- signals.task_postrun.disconnect(self._trace_postrun)
- signals.before_task_publish.disconnect(self._trace_before_publish)
- signals.after_task_publish.disconnect(self._trace_after_publish)
- signals.task_failure.disconnect(self._trace_failure)
- signals.task_retry.disconnect(self._trace_retry)
-
- def _trace_prerun(self, *args, **kwargs):
- task = utils.retrieve_task(kwargs)
- task_id = utils.retrieve_task_id(kwargs)
-
- if task is None or task_id is None:
- return
-
- request = task.request
- tracectx = propagators.extract(carrier_getter, request) or None
-
- logger.debug("prerun signal start task_id=%s", task_id)
-
- operation_name = "{0}/{1}".format(_TASK_RUN, task.name)
- span = self._tracer.start_span(
- operation_name, context=tracectx, kind=trace.SpanKind.CONSUMER
- )
-
- activation = self._tracer.use_span(span, end_on_exit=True)
- activation.__enter__()
- utils.attach_span(task, task_id, (span, activation))
-
- @staticmethod
- def _trace_postrun(*args, **kwargs):
- task = utils.retrieve_task(kwargs)
- task_id = utils.retrieve_task_id(kwargs)
-
- if task is None or task_id is None:
- return
-
- logger.debug("postrun signal task_id=%s", task_id)
-
- # retrieve and finish the Span
- span, activation = utils.retrieve_span(task, task_id)
- if span is None:
- logger.warning("no existing span found for task_id=%s", task_id)
- return
-
- # request context tags
- if span.is_recording():
- span.set_attribute(_TASK_TAG_KEY, _TASK_RUN)
- utils.set_attributes_from_context(span, kwargs)
- utils.set_attributes_from_context(span, task.request)
- span.set_attribute(_TASK_NAME_KEY, task.name)
-
- activation.__exit__(None, None, None)
- utils.detach_span(task, task_id)
-
- def _trace_before_publish(self, *args, **kwargs):
- task = utils.retrieve_task_from_sender(kwargs)
- task_id = utils.retrieve_task_id_from_message(kwargs)
-
- if task is None or task_id is None:
- return
-
- operation_name = "{0}/{1}".format(_TASK_APPLY_ASYNC, task.name)
- span = self._tracer.start_span(
- operation_name, kind=trace.SpanKind.PRODUCER
- )
-
- # apply some attributes here because most of the data is not available
- if span.is_recording():
- span.set_attribute(_TASK_TAG_KEY, _TASK_APPLY_ASYNC)
- span.set_attribute(_MESSAGE_ID_ATTRIBUTE_NAME, task_id)
- span.set_attribute(_TASK_NAME_KEY, task.name)
- utils.set_attributes_from_context(span, kwargs)
-
- activation = self._tracer.use_span(span, end_on_exit=True)
- activation.__enter__()
- utils.attach_span(task, task_id, (span, activation), is_publish=True)
-
- headers = kwargs.get("headers")
- if headers:
- propagators.inject(type(headers).__setitem__, headers)
-
- @staticmethod
- def _trace_after_publish(*args, **kwargs):
- task = utils.retrieve_task_from_sender(kwargs)
- task_id = utils.retrieve_task_id_from_message(kwargs)
-
- if task is None or task_id is None:
- return
-
- # retrieve and finish the Span
- _, activation = utils.retrieve_span(task, task_id, is_publish=True)
- if activation is None:
- logger.warning("no existing span found for task_id=%s", task_id)
- return
-
- activation.__exit__(None, None, None)
- utils.detach_span(task, task_id, is_publish=True)
-
- @staticmethod
- def _trace_failure(*args, **kwargs):
- task = utils.retrieve_task_from_sender(kwargs)
- task_id = utils.retrieve_task_id(kwargs)
-
- if task is None or task_id is None:
- return
-
- # retrieve and pass exception info to activation
- span, _ = utils.retrieve_span(task, task_id)
- if span is None or not span.is_recording():
- return
-
- status_kwargs = {"status_code": StatusCode.ERROR}
-
- ex = kwargs.get("einfo")
-
- if (
- hasattr(task, "throws")
- and ex is not None
- and isinstance(ex.exception, task.throws)
- ):
- return
-
- if ex is not None:
- status_kwargs["description"] = str(ex)
- span.set_status(Status(**status_kwargs))
-
- @staticmethod
- def _trace_retry(*args, **kwargs):
- task = utils.retrieve_task_from_sender(kwargs)
- task_id = utils.retrieve_task_id_from_request(kwargs)
- reason = utils.retrieve_reason(kwargs)
-
- if task is None or task_id is None or reason is None:
- return
-
- span, _ = utils.retrieve_span(task, task_id)
- if span is None or not span.is_recording():
- return
-
- # Add retry reason metadata to span
- # Use `str(reason)` instead of `reason.message` in case we get
- # something that isn't an `Exception`
- span.set_attribute(_TASK_RETRY_REASON_KEY, str(reason))
diff --git a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py
deleted file mode 100644
index 9a441345981..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py
+++ /dev/null
@@ -1,221 +0,0 @@
-# Copyright The OpenTelemetry 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 celery import registry # pylint: disable=no-name-in-module
-
-logger = logging.getLogger(__name__)
-
-# Celery Context key
-CTX_KEY = "__otel_task_span"
-
-# Celery Context attributes
-CELERY_CONTEXT_ATTRIBUTES = (
- "compression",
- "correlation_id",
- "countdown",
- "delivery_info",
- "declare",
- "eta",
- "exchange",
- "expires",
- "hostname",
- "id",
- "priority",
- "queue",
- "reply_to",
- "retries",
- "routing_key",
- "serializer",
- "timelimit",
- "origin",
- "state",
-)
-
-
-# pylint:disable=too-many-branches
-def set_attributes_from_context(span, context):
- """Helper to extract meta values from a Celery Context"""
- if not span.is_recording():
- return
- for key in CELERY_CONTEXT_ATTRIBUTES:
- value = context.get(key)
-
- # Skip this key if it is not set
- if value is None or value == "":
- continue
-
- # Skip `timelimit` if it is not set (it's default/unset value is a
- # tuple or a list of `None` values
- if key == "timelimit" and value in [(None, None), [None, None]]:
- continue
-
- # Skip `retries` if it's value is `0`
- if key == "retries" and value == 0:
- continue
-
- attribute_name = None
-
- # Celery 4.0 uses `origin` instead of `hostname`; this change preserves
- # the same name for the tag despite Celery version
- if key == "origin":
- key = "hostname"
-
- elif key == "delivery_info":
- # Get also destination from this
- routing_key = value.get("routing_key")
- if routing_key is not None:
- span.set_attribute("messaging.destination", routing_key)
- value = str(value)
-
- elif key == "id":
- attribute_name = "messaging.message_id"
-
- elif key == "correlation_id":
- attribute_name = "messaging.conversation_id"
-
- elif key == "routing_key":
- attribute_name = "messaging.destination"
-
- # according to https://docs.celeryproject.org/en/stable/userguide/routing.html#exchange-types
- elif key == "declare":
- attribute_name = "messaging.destination_kind"
- for declare in value:
- if declare.exchange.type == "direct":
- value = "queue"
- break
- if declare.exchange.type == "topic":
- value = "topic"
- break
-
- # set attribute name if not set specially for a key
- if attribute_name is None:
- attribute_name = "celery.{}".format(key)
-
- span.set_attribute(attribute_name, value)
-
-
-def attach_span(task, task_id, span, is_publish=False):
- """Helper to propagate a `Span` for the given `Task` instance. This
- function uses a `dict` that stores the Span using the
- `(task_id, is_publish)` as a key. This is useful when information must be
- propagated from one Celery signal to another.
-
- We use (task_id, is_publish) for the key to ensure that publishing a
- task from within another task does not cause any conflicts.
-
- This mostly happens when either a task fails and a retry policy is in place,
- or when a task is manually retries (e.g. `task.retry()`), we end up trying
- to publish a task with the same id as the task currently running.
-
- Previously publishing the new task would overwrite the existing `celery.run` span
- in the `dict` causing that span to be forgotten and never finished
- NOTE: We cannot test for this well yet, because we do not run a celery worker,
- and cannot run `task.apply_async()`
- """
- span_dict = getattr(task, CTX_KEY, None)
- if span_dict is None:
- span_dict = dict()
- setattr(task, CTX_KEY, span_dict)
-
- span_dict[(task_id, is_publish)] = span
-
-
-def detach_span(task, task_id, is_publish=False):
- """Helper to remove a `Span` in a Celery task when it's propagated.
- This function handles tasks where the `Span` is not attached.
- """
- span_dict = getattr(task, CTX_KEY, None)
- if span_dict is None:
- return
-
- # See note in `attach_span` for key info
- span_dict.pop((task_id, is_publish), (None, None))
-
-
-def retrieve_span(task, task_id, is_publish=False):
- """Helper to retrieve an active `Span` stored in a `Task`
- instance
- """
- span_dict = getattr(task, CTX_KEY, None)
- if span_dict is None:
- return (None, None)
-
- # See note in `attach_span` for key info
- return span_dict.get((task_id, is_publish), (None, None))
-
-
-def retrieve_task(kwargs):
- task = kwargs.get("task")
- if task is None:
- logger.debug("Unable to retrieve task from signal arguments")
- return task
-
-
-def retrieve_task_from_sender(kwargs):
- sender = kwargs.get("sender")
- if sender is None:
- logger.debug("Unable to retrieve the sender from signal arguments")
-
- # before and after publish signals sender is the task name
- # for retry and failure signals sender is the task object
- if isinstance(sender, str):
- sender = registry.tasks.get(sender)
- if sender is None:
- logger.debug("Unable to retrieve the task from sender=%s", sender)
-
- return sender
-
-
-def retrieve_task_id(kwargs):
- task_id = kwargs.get("task_id")
- if task_id is None:
- logger.debug("Unable to retrieve task_id from signal arguments")
- return task_id
-
-
-def retrieve_task_id_from_request(kwargs):
- # retry signal does not include task_id as argument so use request argument
- request = kwargs.get("request")
- if request is None:
- logger.debug("Unable to retrieve the request from signal arguments")
-
- task_id = getattr(request, "id")
- if task_id is None:
- logger.debug("Unable to retrieve the task_id from the request")
-
- return task_id
-
-
-def retrieve_task_id_from_message(kwargs):
- """Helper to retrieve the `Task` identifier from the message `body`.
- This helper supports Protocol Version 1 and 2. The Protocol is well
- detailed in the official documentation:
- http://docs.celeryproject.org/en/latest/internals/protocol.html
- """
- headers = kwargs.get("headers")
- body = kwargs.get("body")
- if headers is not None and len(headers) > 0:
- # Protocol Version 2 (default from Celery 4.0)
- return headers.get("id")
- # Protocol Version 1
- return body.get("id")
-
-
-def retrieve_reason(kwargs):
- reason = kwargs.get("reason")
- if not reason:
- logger.debug("Unable to retrieve the retry reason")
- return reason
diff --git a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/version.py b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-celery/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-celery/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-celery/tests/celery_test_tasks.py b/instrumentation/opentelemetry-instrumentation-celery/tests/celery_test_tasks.py
deleted file mode 100644
index d9660412f04..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/tests/celery_test_tasks.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright The OpenTelemetry 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 celery import Celery
-
-
-class Config:
- result_backend = "rpc"
- broker_backend = "memory"
-
-
-app = Celery(broker="memory:///")
-app.config_from_object(Config)
-
-
-@app.task
-def task_add(num_a, num_b):
- return num_a + num_b
diff --git a/instrumentation/opentelemetry-instrumentation-celery/tests/test_tasks.py b/instrumentation/opentelemetry-instrumentation-celery/tests/test_tasks.py
deleted file mode 100644
index 3a05ebf331a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/tests/test_tasks.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright The OpenTelemetry 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 threading
-import time
-
-from opentelemetry.instrumentation.celery import CeleryInstrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace import SpanKind
-
-from .celery_test_tasks import app, task_add
-
-
-class TestCeleryInstrumentation(TestBase):
- def setUp(self):
- super().setUp()
- self._worker = app.Worker(app=app, pool="solo", concurrency=1)
- self._thread = threading.Thread(target=self._worker.start)
- self._thread.daemon = True
- self._thread.start()
-
- def tearDown(self):
- super().tearDown()
- self._worker.stop()
- self._thread.join()
-
- def test_task(self):
- CeleryInstrumentor().instrument()
-
- result = task_add.delay(1, 2)
- while not result.ready():
- time.sleep(0.05)
-
- spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
- self.assertEqual(len(spans), 2)
-
- consumer, producer = spans
-
- self.assertEqual(consumer.name, "run/tests.celery_test_tasks.task_add")
- self.assertEqual(consumer.kind, SpanKind.CONSUMER)
- self.assert_span_has_attributes(
- consumer,
- {
- "celery.action": "run",
- "celery.state": "SUCCESS",
- "messaging.destination": "celery",
- "celery.task_name": "tests.celery_test_tasks.task_add",
- },
- )
-
- self.assertEqual(
- producer.name, "apply_async/tests.celery_test_tasks.task_add"
- )
- self.assertEqual(producer.kind, SpanKind.PRODUCER)
- self.assert_span_has_attributes(
- producer,
- {
- "celery.action": "apply_async",
- "celery.task_name": "tests.celery_test_tasks.task_add",
- "messaging.destination_kind": "queue",
- "messaging.destination": "celery",
- },
- )
-
- self.assertNotEqual(consumer.parent, producer.context)
- self.assertEqual(consumer.parent.span_id, producer.context.span_id)
- self.assertEqual(consumer.context.trace_id, producer.context.trace_id)
diff --git a/instrumentation/opentelemetry-instrumentation-celery/tests/test_utils.py b/instrumentation/opentelemetry-instrumentation-celery/tests/test_utils.py
deleted file mode 100644
index f48f06aafbe..00000000000
--- a/instrumentation/opentelemetry-instrumentation-celery/tests/test_utils.py
+++ /dev/null
@@ -1,232 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest
-from unittest import mock
-
-from celery import Celery
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.celery import utils
-from opentelemetry.sdk import trace
-
-
-class TestUtils(unittest.TestCase):
- def setUp(self):
- self.app = Celery("celery.test_app")
-
- def test_set_attributes_from_context(self):
- # it should extract only relevant keys
- context = {
- "correlation_id": "44b7f305",
- "delivery_info": {"eager": True},
- "eta": "soon",
- "expires": "later",
- "hostname": "localhost",
- "id": "44b7f305",
- "reply_to": "44b7f305",
- "retries": 4,
- "timelimit": ("now", "later"),
- "custom_meta": "custom_value",
- "routing_key": "celery",
- }
-
- span = trace._Span("name", mock.Mock(spec=trace_api.SpanContext))
- utils.set_attributes_from_context(span, context)
-
- self.assertEqual(
- span.attributes.get("messaging.message_id"), "44b7f305"
- )
- self.assertEqual(
- span.attributes.get("messaging.conversation_id"), "44b7f305"
- )
- self.assertEqual(
- span.attributes.get("messaging.destination"), "celery"
- )
-
- self.assertEqual(
- span.attributes["celery.delivery_info"], str({"eager": True})
- )
- self.assertEqual(span.attributes.get("celery.eta"), "soon")
- self.assertEqual(span.attributes.get("celery.expires"), "later")
- self.assertEqual(span.attributes.get("celery.hostname"), "localhost")
-
- self.assertEqual(span.attributes.get("celery.reply_to"), "44b7f305")
- self.assertEqual(span.attributes.get("celery.retries"), 4)
- self.assertEqual(
- span.attributes.get("celery.timelimit"), ("now", "later")
- )
- self.assertNotIn("custom_meta", span.attributes)
-
- def test_set_attributes_not_recording(self):
- # it should extract only relevant keys
- context = {
- "correlation_id": "44b7f305",
- "delivery_info": {"eager": True},
- "eta": "soon",
- "expires": "later",
- "hostname": "localhost",
- "id": "44b7f305",
- "reply_to": "44b7f305",
- "retries": 4,
- "timelimit": ("now", "later"),
- "custom_meta": "custom_value",
- "routing_key": "celery",
- }
-
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- utils.set_attributes_from_context(mock_span, context)
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_set_attributes_from_context_empty_keys(self):
- # it should not extract empty keys
- context = {
- "correlation_id": None,
- "exchange": "",
- "timelimit": (None, None),
- "retries": 0,
- }
-
- span = trace._Span("name", mock.Mock(spec=trace_api.SpanContext))
- utils.set_attributes_from_context(span, context)
-
- self.assertEqual(len(span.attributes), 0)
- # edge case: `timelimit` can also be a list of None values
- context = {
- "timelimit": [None, None],
- }
-
- utils.set_attributes_from_context(span, context)
-
- self.assertEqual(len(span.attributes), 0)
-
- def test_span_propagation(self):
- # ensure spans getter and setter works properly
- @self.app.task
- def fn_task():
- return 42
-
- # propagate and retrieve a Span
- task_id = "7c6731af-9533-40c3-83a9-25b58f0d837f"
- span = trace._Span("name", mock.Mock(spec=trace_api.SpanContext))
- utils.attach_span(fn_task, task_id, span)
- span_after = utils.retrieve_span(fn_task, task_id)
- self.assertIs(span, span_after)
-
- def test_span_delete(self):
- # ensure the helper removes properly a propagated Span
- @self.app.task
- def fn_task():
- return 42
-
- # propagate a Span
- task_id = "7c6731af-9533-40c3-83a9-25b58f0d837f"
- span = trace._Span("name", mock.Mock(spec=trace_api.SpanContext))
- utils.attach_span(fn_task, task_id, span)
- # delete the Span
- utils.detach_span(fn_task, task_id)
- self.assertEqual(utils.retrieve_span(fn_task, task_id), (None, None))
-
- def test_span_delete_empty(self):
- # ensure detach_span doesn't raise an exception if span is not present
- @self.app.task
- def fn_task():
- return 42
-
- # delete the Span
- task_id = "7c6731af-9533-40c3-83a9-25b58f0d837f"
- try:
- utils.detach_span(fn_task, task_id)
- self.assertEqual(
- utils.retrieve_span(fn_task, task_id), (None, None)
- )
- except Exception as ex: # pylint: disable=broad-except
- self.fail("Exception was raised: %s" % ex)
-
- def test_task_id_from_protocol_v1(self):
- # ensures a `task_id` is properly returned when Protocol v1 is used.
- # `context` is an example of an emitted Signal with Protocol v1
- context = {
- "body": {
- "expires": None,
- "utc": True,
- "args": ["user"],
- "chord": None,
- "callbacks": None,
- "errbacks": None,
- "taskset": None,
- "id": "dffcaec1-dd92-4a1a-b3ab-d6512f4beeb7",
- "retries": 0,
- "task": "tests.contrib.celery.test_integration.fn_task_parameters",
- "timelimit": (None, None),
- "eta": None,
- "kwargs": {"force_logout": True},
- },
- "sender": "tests.contrib.celery.test_integration.fn_task_parameters",
- "exchange": "celery",
- "routing_key": "celery",
- "retry_policy": None,
- "headers": {},
- "properties": {},
- }
-
- task_id = utils.retrieve_task_id_from_message(context)
- self.assertEqual(task_id, "dffcaec1-dd92-4a1a-b3ab-d6512f4beeb7")
-
- def test_task_id_from_protocol_v2(self):
- # ensures a `task_id` is properly returned when Protocol v2 is used.
- # `context` is an example of an emitted Signal with Protocol v2
- context = {
- "body": (
- ["user"],
- {"force_logout": True},
- {
- u"chord": None,
- u"callbacks": None,
- u"errbacks": None,
- u"chain": None,
- },
- ),
- "sender": u"tests.contrib.celery.test_integration.fn_task_parameters",
- "exchange": u"",
- "routing_key": u"celery",
- "retry_policy": None,
- "headers": {
- u"origin": u"gen83744@hostname",
- u"root_id": "7e917b83-4018-431d-9832-73a28e1fb6c0",
- u"expires": None,
- u"shadow": None,
- u"id": "7e917b83-4018-431d-9832-73a28e1fb6c0",
- u"kwargsrepr": u"{'force_logout': True}",
- u"lang": u"py",
- u"retries": 0,
- u"task": u"tests.contrib.celery.test_integration.fn_task_parameters",
- u"group": None,
- u"timelimit": [None, None],
- u"parent_id": None,
- u"argsrepr": u"['user']",
- u"eta": None,
- },
- "properties": {
- u"reply_to": "c3054a07-5b28-3855-b18c-1623a24aaeca",
- u"correlation_id": "7e917b83-4018-431d-9832-73a28e1fb6c0",
- },
- }
-
- task_id = utils.retrieve_task_id_from_message(context)
- self.assertEqual(task_id, "7e917b83-4018-431d-9832-73a28e1fb6c0")
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-dbapi/CHANGELOG.md
deleted file mode 100644
index e110055da1a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-dbapi/CHANGELOG.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- bugfix: cursors and connections now produce spans when used with context managers
- ([#1028](https://github.com/open-telemetry/opentelemetry-python/pull/1028))
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-dbapi
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Implement instrument_connection and uninstrument_connection ([#624](https://github.com/open-telemetry/opentelemetry-python/pull/624))
-
-## 0.4a0
-
-Released 2020-02-21
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/LICENSE b/instrumentation/opentelemetry-instrumentation-dbapi/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-dbapi/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-dbapi/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-dbapi/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-dbapi/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/README.rst b/instrumentation/opentelemetry-instrumentation-dbapi/README.rst
deleted file mode 100644
index 5137a1c1ff7..00000000000
--- a/instrumentation/opentelemetry-instrumentation-dbapi/README.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-OpenTelemetry Database API instrumentation
-==========================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-dbapi.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-dbapi/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-dbapi
-
-
-References
-----------
-
-* `OpenTelemetry Database API Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/setup.cfg b/instrumentation/opentelemetry-instrumentation-dbapi/setup.cfg
deleted file mode 100644
index 7c4daa40299..00000000000
--- a/instrumentation/opentelemetry-instrumentation-dbapi/setup.cfg
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-dbapi
-description = OpenTelemetry Database API instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-dbapi
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- wrapt >= 1.0.0, < 2.0.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/setup.py b/instrumentation/opentelemetry-instrumentation-dbapi/setup.py
deleted file mode 100644
index cfe98f38952..00000000000
--- a/instrumentation/opentelemetry-instrumentation-dbapi/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "dbapi", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py
deleted file mode 100644
index 0047ab18517..00000000000
--- a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py
+++ /dev/null
@@ -1,385 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-The trace integration with Database API supports libraries that follow the
-Python Database API Specification v2.0.
-``_
-
-Usage
------
-
-.. code-block:: python
-
- import mysql.connector
- import pyodbc
-
- from opentelemetry import trace
- from opentelemetry.instrumentation.dbapi import trace_integration
- from opentelemetry.trace import TracerProvider
-
- trace.set_tracer_provider(TracerProvider())
-
- # Ex: mysql.connector
- trace_integration(mysql.connector, "connect", "mysql", "sql")
- # Ex: pyodbc
- trace_integration(pyodbc, "Connection", "odbc", "sql")
-
-API
----
-"""
-
-import functools
-import logging
-import typing
-
-import wrapt
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.dbapi.version import __version__
-from opentelemetry.instrumentation.utils import unwrap
-from opentelemetry.trace import SpanKind, TracerProvider, get_tracer
-from opentelemetry.trace.status import Status, StatusCode
-
-logger = logging.getLogger(__name__)
-
-
-def trace_integration(
- connect_module: typing.Callable[..., typing.Any],
- connect_method_name: str,
- database_component: str,
- database_type: str = "",
- connection_attributes: typing.Dict = None,
- tracer_provider: typing.Optional[TracerProvider] = None,
-):
- """Integrate with DB API library.
- https://www.python.org/dev/peps/pep-0249/
-
- Args:
- connect_module: Module name where connect method is available.
- connect_method_name: The connect method name.
- database_component: Database driver name or database name "JDBI",
- "jdbc", "odbc", "postgreSQL".
- database_type: The Database type. For any SQL database, "sql".
- connection_attributes: Attribute names for database, port, host and
- user in Connection object.
- tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to
- use. If ommited the current configured one is used.
- """
- wrap_connect(
- __name__,
- connect_module,
- connect_method_name,
- database_component,
- database_type,
- connection_attributes,
- version=__version__,
- tracer_provider=tracer_provider,
- )
-
-
-def wrap_connect(
- name: str,
- connect_module: typing.Callable[..., typing.Any],
- connect_method_name: str,
- database_component: str,
- database_type: str = "",
- connection_attributes: typing.Dict = None,
- version: str = "",
- tracer_provider: typing.Optional[TracerProvider] = None,
-):
- """Integrate with DB API library.
- https://www.python.org/dev/peps/pep-0249/
-
- Args:
- tracer: The :class:`opentelemetry.trace.Tracer` to use.
- connect_module: Module name where connect method is available.
- connect_method_name: The connect method name.
- database_component: Database driver name or database name "JDBI",
- "jdbc", "odbc", "postgreSQL".
- database_type: The Database type. For any SQL database, "sql".
- connection_attributes: Attribute names for database, port, host and
- user in Connection object.
- """
-
- # pylint: disable=unused-argument
- def wrap_connect_(
- wrapped: typing.Callable[..., typing.Any],
- instance: typing.Any,
- args: typing.Tuple[typing.Any, typing.Any],
- kwargs: typing.Dict[typing.Any, typing.Any],
- ):
- db_integration = DatabaseApiIntegration(
- name,
- database_component,
- database_type=database_type,
- connection_attributes=connection_attributes,
- version=version,
- tracer_provider=tracer_provider,
- )
- return db_integration.wrapped_connection(wrapped, args, kwargs)
-
- try:
- wrapt.wrap_function_wrapper(
- connect_module, connect_method_name, wrap_connect_
- )
- except Exception as ex: # pylint: disable=broad-except
- logger.warning("Failed to integrate with DB API. %s", str(ex))
-
-
-def unwrap_connect(
- connect_module: typing.Callable[..., typing.Any], connect_method_name: str,
-):
- """Disable integration with DB API library.
- https://www.python.org/dev/peps/pep-0249/
-
- Args:
- connect_module: Module name where the connect method is available.
- connect_method_name: The connect method name.
- """
- unwrap(connect_module, connect_method_name)
-
-
-def instrument_connection(
- name: str,
- connection,
- database_component: str,
- database_type: str = "",
- connection_attributes: typing.Dict = None,
- version: str = "",
- tracer_provider: typing.Optional[TracerProvider] = None,
-):
- """Enable instrumentation in a database connection.
-
- Args:
- tracer: The :class:`opentelemetry.trace.Tracer` to use.
- connection: The connection to instrument.
- database_component: Database driver name or database name "JDBI",
- "jdbc", "odbc", "postgreSQL".
- database_type: The Database type. For any SQL database, "sql".
- connection_attributes: Attribute names for database, port, host and
- user in a connection object.
-
- Returns:
- An instrumented connection.
- """
- db_integration = DatabaseApiIntegration(
- name,
- database_component,
- database_type,
- connection_attributes=connection_attributes,
- version=version,
- tracer_provider=tracer_provider,
- )
- db_integration.get_connection_attributes(connection)
- return get_traced_connection_proxy(connection, db_integration)
-
-
-def uninstrument_connection(connection):
- """Disable instrumentation in a database connection.
-
- Args:
- connection: The connection to uninstrument.
-
- Returns:
- An uninstrumented connection.
- """
- if isinstance(connection, wrapt.ObjectProxy):
- return connection.__wrapped__
-
- logger.warning("Connection is not instrumented")
- return connection
-
-
-class DatabaseApiIntegration:
- def __init__(
- self,
- name: str,
- database_component: str,
- database_type: str = "sql",
- connection_attributes=None,
- version: str = "",
- tracer_provider: typing.Optional[TracerProvider] = None,
- ):
- self.connection_attributes = connection_attributes
- if self.connection_attributes is None:
- self.connection_attributes = {
- "database": "database",
- "port": "port",
- "host": "host",
- "user": "user",
- }
- self._name = name
- self._version = version
- self._tracer_provider = tracer_provider
- self.database_component = database_component
- self.database_type = database_type
- self.connection_props = {}
- self.span_attributes = {}
- self.name = ""
- self.database = ""
-
- def get_tracer(self):
- return get_tracer(
- self._name,
- instrumenting_library_version=self._version,
- tracer_provider=self._tracer_provider,
- )
-
- def wrapped_connection(
- self,
- connect_method: typing.Callable[..., typing.Any],
- args: typing.Tuple[typing.Any, typing.Any],
- kwargs: typing.Dict[typing.Any, typing.Any],
- ):
- """Add object proxy to connection object.
- """
- connection = connect_method(*args, **kwargs)
- self.get_connection_attributes(connection)
- return get_traced_connection_proxy(connection, self)
-
- def get_connection_attributes(self, connection):
- # Populate span fields using connection
- for key, value in self.connection_attributes.items():
- # Allow attributes nested in connection object
- attribute = functools.reduce(
- lambda attribute, attribute_value: getattr(
- attribute, attribute_value, None
- ),
- value.split("."),
- connection,
- )
- if attribute:
- self.connection_props[key] = attribute
- self.name = self.database_component
- self.database = self.connection_props.get("database", "")
- if self.database:
- # PyMySQL encodes names with utf-8
- if hasattr(self.database, "decode"):
- self.database = self.database.decode(errors="ignore")
- self.name += "." + self.database
- user = self.connection_props.get("user")
- if user is not None:
- self.span_attributes["db.user"] = str(user)
- host = self.connection_props.get("host")
- if host is not None:
- self.span_attributes["net.peer.name"] = host
- port = self.connection_props.get("port")
- if port is not None:
- self.span_attributes["net.peer.port"] = port
-
-
-def get_traced_connection_proxy(
- connection, db_api_integration, *args, **kwargs
-):
- # pylint: disable=abstract-method
- class TracedConnectionProxy(wrapt.ObjectProxy):
- # pylint: disable=unused-argument
- def __init__(self, connection, *args, **kwargs):
- wrapt.ObjectProxy.__init__(self, connection)
-
- def cursor(self, *args, **kwargs):
- return get_traced_cursor_proxy(
- self.__wrapped__.cursor(*args, **kwargs), db_api_integration
- )
-
- def __enter__(self):
- self.__wrapped__.__enter__()
- return self
-
- def __exit__(self, *args, **kwargs):
- self.__wrapped__.__exit__(*args, **kwargs)
-
- return TracedConnectionProxy(connection, *args, **kwargs)
-
-
-class TracedCursor:
- def __init__(self, db_api_integration: DatabaseApiIntegration):
- self._db_api_integration = db_api_integration
-
- def _populate_span(
- self, span: trace_api.Span, *args: typing.Tuple[typing.Any, typing.Any]
- ):
- if not span.is_recording():
- return
- statement = args[0] if args else ""
- span.set_attribute(
- "component", self._db_api_integration.database_component
- )
- span.set_attribute("db.type", self._db_api_integration.database_type)
- span.set_attribute("db.instance", self._db_api_integration.database)
- span.set_attribute("db.statement", statement)
-
- for (
- attribute_key,
- attribute_value,
- ) in self._db_api_integration.span_attributes.items():
- span.set_attribute(attribute_key, attribute_value)
-
- if len(args) > 1:
- span.set_attribute("db.statement.parameters", str(args[1]))
-
- def traced_execution(
- self,
- query_method: typing.Callable[..., typing.Any],
- *args: typing.Tuple[typing.Any, typing.Any],
- **kwargs: typing.Dict[typing.Any, typing.Any]
- ):
-
- with self._db_api_integration.get_tracer().start_as_current_span(
- self._db_api_integration.name, kind=SpanKind.CLIENT
- ) as span:
- self._populate_span(span, *args)
- try:
- result = query_method(*args, **kwargs)
- return result
- except Exception as ex: # pylint: disable=broad-except
- if span.is_recording():
- span.set_status(Status(StatusCode.ERROR, str(ex)))
- raise ex
-
-
-def get_traced_cursor_proxy(cursor, db_api_integration, *args, **kwargs):
- _traced_cursor = TracedCursor(db_api_integration)
-
- # pylint: disable=abstract-method
- class TracedCursorProxy(wrapt.ObjectProxy):
-
- # pylint: disable=unused-argument
- def __init__(self, cursor, *args, **kwargs):
- wrapt.ObjectProxy.__init__(self, cursor)
-
- def execute(self, *args, **kwargs):
- return _traced_cursor.traced_execution(
- self.__wrapped__.execute, *args, **kwargs
- )
-
- def executemany(self, *args, **kwargs):
- return _traced_cursor.traced_execution(
- self.__wrapped__.executemany, *args, **kwargs
- )
-
- def callproc(self, *args, **kwargs):
- return _traced_cursor.traced_execution(
- self.__wrapped__.callproc, *args, **kwargs
- )
-
- def __enter__(self):
- self.__wrapped__.__enter__()
- return self
-
- def __exit__(self, *args, **kwargs):
- self.__wrapped__.__exit__(*args, **kwargs)
-
- return TracedCursorProxy(cursor, *args, **kwargs)
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/version.py b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-dbapi/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py b/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py
deleted file mode 100644
index f2abb8b6dca..00000000000
--- a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py
+++ /dev/null
@@ -1,229 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest import mock
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation import dbapi
-from opentelemetry.test.test_base import TestBase
-
-
-class TestDBApiIntegration(TestBase):
- def setUp(self):
- super().setUp()
- self.tracer = self.tracer_provider.get_tracer(__name__)
-
- def test_span_succeeded(self):
- connection_props = {
- "database": "testdatabase",
- "server_host": "testhost",
- "server_port": 123,
- "user": "testuser",
- }
- connection_attributes = {
- "database": "database",
- "port": "server_port",
- "host": "server_host",
- "user": "user",
- }
- db_integration = dbapi.DatabaseApiIntegration(
- self.tracer, "testcomponent", "testtype", connection_attributes
- )
- mock_connection = db_integration.wrapped_connection(
- mock_connect, {}, connection_props
- )
- cursor = mock_connection.cursor()
- cursor.execute("Test query", ("param1Value", False))
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(span.name, "testcomponent.testdatabase")
- self.assertIs(span.kind, trace_api.SpanKind.CLIENT)
-
- self.assertEqual(span.attributes["component"], "testcomponent")
- self.assertEqual(span.attributes["db.type"], "testtype")
- self.assertEqual(span.attributes["db.instance"], "testdatabase")
- self.assertEqual(span.attributes["db.statement"], "Test query")
- self.assertEqual(
- span.attributes["db.statement.parameters"],
- "('param1Value', False)",
- )
- self.assertEqual(span.attributes["db.user"], "testuser")
- self.assertEqual(span.attributes["net.peer.name"], "testhost")
- self.assertEqual(span.attributes["net.peer.port"], 123)
- self.assertIs(
- span.status.status_code, trace_api.status.StatusCode.UNSET,
- )
-
- def test_span_not_recording(self):
- connection_props = {
- "database": "testdatabase",
- "server_host": "testhost",
- "server_port": 123,
- "user": "testuser",
- }
- connection_attributes = {
- "database": "database",
- "port": "server_port",
- "host": "server_host",
- "user": "user",
- }
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- db_integration = dbapi.DatabaseApiIntegration(
- mock_tracer, "testcomponent", "testtype", connection_attributes
- )
- mock_connection = db_integration.wrapped_connection(
- mock_connect, {}, connection_props
- )
- cursor = mock_connection.cursor()
- cursor.execute("Test query", ("param1Value", False))
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_span_failed(self):
- db_integration = dbapi.DatabaseApiIntegration(
- self.tracer, "testcomponent"
- )
- mock_connection = db_integration.wrapped_connection(
- mock_connect, {}, {}
- )
- cursor = mock_connection.cursor()
- with self.assertRaises(Exception):
- cursor.execute("Test query", throw_exception=True)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(span.attributes["db.statement"], "Test query")
- self.assertIs(
- span.status.status_code, trace_api.status.StatusCode.ERROR,
- )
- self.assertEqual(span.status.description, "Test Exception")
-
- def test_executemany(self):
- db_integration = dbapi.DatabaseApiIntegration(
- self.tracer, "testcomponent"
- )
- mock_connection = db_integration.wrapped_connection(
- mock_connect, {}, {}
- )
- cursor = mock_connection.cursor()
- cursor.executemany("Test query")
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(span.attributes["db.statement"], "Test query")
-
- def test_callproc(self):
- db_integration = dbapi.DatabaseApiIntegration(
- self.tracer, "testcomponent"
- )
- mock_connection = db_integration.wrapped_connection(
- mock_connect, {}, {}
- )
- cursor = mock_connection.cursor()
- cursor.callproc("Test stored procedure")
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(
- span.attributes["db.statement"], "Test stored procedure"
- )
-
- @mock.patch("opentelemetry.instrumentation.dbapi")
- def test_wrap_connect(self, mock_dbapi):
- dbapi.wrap_connect(self.tracer, mock_dbapi, "connect", "-")
- connection = mock_dbapi.connect()
- self.assertEqual(mock_dbapi.connect.call_count, 1)
- self.assertIsInstance(connection.__wrapped__, mock.Mock)
-
- @mock.patch("opentelemetry.instrumentation.dbapi")
- def test_unwrap_connect(self, mock_dbapi):
- dbapi.wrap_connect(self.tracer, mock_dbapi, "connect", "-")
- connection = mock_dbapi.connect()
- self.assertEqual(mock_dbapi.connect.call_count, 1)
-
- dbapi.unwrap_connect(mock_dbapi, "connect")
- connection = mock_dbapi.connect()
- self.assertEqual(mock_dbapi.connect.call_count, 2)
- self.assertIsInstance(connection, mock.Mock)
-
- def test_instrument_connection(self):
- connection = mock.Mock()
- # Avoid get_attributes failing because can't concatenate mock
- connection.database = "-"
- connection2 = dbapi.instrument_connection(self.tracer, connection, "-")
- self.assertIs(connection2.__wrapped__, connection)
-
- def test_uninstrument_connection(self):
- connection = mock.Mock()
- # Set connection.database to avoid a failure because mock can't
- # be concatenated
- connection.database = "-"
- connection2 = dbapi.instrument_connection(self.tracer, connection, "-")
- self.assertIs(connection2.__wrapped__, connection)
-
- connection3 = dbapi.uninstrument_connection(connection2)
- self.assertIs(connection3, connection)
-
- with self.assertLogs(level=logging.WARNING):
- connection4 = dbapi.uninstrument_connection(connection)
- self.assertIs(connection4, connection)
-
-
-# pylint: disable=unused-argument
-def mock_connect(*args, **kwargs):
- database = kwargs.get("database")
- server_host = kwargs.get("server_host")
- server_port = kwargs.get("server_port")
- user = kwargs.get("user")
- return MockConnection(database, server_port, server_host, user)
-
-
-class MockConnection:
- def __init__(self, database, server_port, server_host, user):
- self.database = database
- self.server_port = server_port
- self.server_host = server_host
- self.user = user
-
- # pylint: disable=no-self-use
- def cursor(self):
- return MockCursor()
-
-
-class MockCursor:
- # pylint: disable=unused-argument, no-self-use
- def execute(self, query, params=None, throw_exception=False):
- if throw_exception:
- raise Exception("Test Exception")
-
- # pylint: disable=unused-argument, no-self-use
- def executemany(self, query, params=None, throw_exception=False):
- if throw_exception:
- raise Exception("Test Exception")
-
- # pylint: disable=unused-argument, no-self-use
- def callproc(self, query, params=None, throw_exception=False):
- if throw_exception:
- raise Exception("Test Exception")
diff --git a/instrumentation/opentelemetry-instrumentation-django/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-django/CHANGELOG.md
deleted file mode 100644
index 5876936a0b5..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/CHANGELOG.md
+++ /dev/null
@@ -1,60 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.15b0
-
-Released 2020-11-02
-
-- Django instrumentation is now enabled by default but can be disabled by setting `OTEL_PYTHON_DJANGO_INSTRUMENT` to `False`
- ([#1239](https://github.com/open-telemetry/opentelemetry-python/pull/1239))
-- Bugfix use request.path replace request.get_full_path(). It will get correct span name
- ([#1309](https://github.com/open-telemetry/opentelemetry-python/pull/1309#))
-- Record span status and http.status_code attribute on exception
- ([#1257](https://github.com/open-telemetry/opentelemetry-python/pull/1257))
-- Added capture of http.route
- ([#1226](https://github.com/open-telemetry/opentelemetry-python/issues/1226))
-- Add support for tracking http metrics
- ([#1230](https://github.com/open-telemetry/opentelemetry-python/pull/1230))
-
-## Version 0.14b0
-
-Released 2020-10-13
-
-- Changed span name extraction from request to comply semantic convention ([#992](https://github.com/open-telemetry/opentelemetry-python/pull/992))
-- Added support for `OTEL_PYTHON_DJANGO_TRACED_REQUEST_ATTRS` ([#1154](https://github.com/open-telemetry/opentelemetry-python/pull/1154))
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-django
- ([#961](https://github.com/open-telemetry/opentelemetry-python/pull/961))
-- Update environment variable names, prefix changed from `OPENTELEMETRY` to `OTEL` ([#904](https://github.com/open-telemetry/opentelemetry-python/pull/904))
-
-## Version 0.11b0
-
-Released 2020-07-28
-
-- Use one general exclude list instead of two ([#872](https://github.com/open-telemetry/opentelemetry-python/pull/872))
-
-## 0.8b0
-
-Released 2020-05-27
-
-- Add exclude list for paths and hosts to prevent from tracing
- ([#670](https://github.com/open-telemetry/opentelemetry-python/pull/670))
-- Add support for django >= 1.10 (#717)
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-django/LICENSE b/instrumentation/opentelemetry-instrumentation-django/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-django/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-django/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-django/README.rst b/instrumentation/opentelemetry-instrumentation-django/README.rst
deleted file mode 100644
index a2b98cabf40..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/README.rst
+++ /dev/null
@@ -1,53 +0,0 @@
-OpenTelemetry Django Tracing
-============================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-django.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-django/
-
-This library allows tracing requests for Django applications.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-django
-
-Configuration
--------------
-
-Exclude lists
-*************
-To exclude certain URLs from being tracked, set the environment variable ``OTEL_PYTHON_DJANGO_EXCLUDED_URLS`` with comma delimited regexes representing which URLs to exclude.
-
-For example,
-
-::
-
- export OTEL_PYTHON_DJANGO_EXCLUDED_URLS="client/.*/info,healthcheck"
-
-will exclude requests such as ``https://site/client/123/info`` and ``https://site/xyz/healthcheck``.
-
-Request attributes
-********************
-To extract certain attributes from Django's request object and use them as span attributes, set the environment variable ``OTEL_PYTHON_DJANGO_TRACED_REQUEST_ATTRS`` to a comma
-delimited list of request attribute names.
-
-For example,
-
-::
-
- export OTEL_PYTHON_DJANGO_TRACED_REQUEST_ATTRS='path_info,content_type'
-
-will extract path_info and content_type attributes from every traced request and add them as span attritbues.
-
-Django Request object reference: https://docs.djangoproject.com/en/3.1/ref/request-response/#attributes
-
-References
-----------
-
-* `Django `_
-* `OpenTelemetry Instrumentation for Django `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-django/setup.cfg b/instrumentation/opentelemetry-instrumentation-django/setup.cfg
deleted file mode 100644
index 44a921283d2..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/setup.cfg
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-django
-description = OpenTelemetry Instrumentation for Django
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-django
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- django >= 1.10
- opentelemetry-instrumentation-wsgi == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- opentelemetry-api == 0.16.dev0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- django = opentelemetry.instrumentation.django:DjangoInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-django/setup.py b/instrumentation/opentelemetry-instrumentation-django/setup.py
deleted file mode 100644
index fb9d615ce30..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/setup.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright The OpenTelemetry 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 os.path import dirname, join
-
-from setuptools import setup
-
-PACKAGE_INFO = {}
-with open(
- join(
- dirname(__file__),
- "src",
- "opentelemetry",
- "instrumentation",
- "django",
- "version.py",
- )
-) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py
deleted file mode 100644
index 26e21a1f7fa..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright The OpenTelemetry 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 logging import getLogger
-
-from django.conf import settings
-
-from opentelemetry.configuration import Configuration
-from opentelemetry.instrumentation.django.middleware import _DjangoMiddleware
-from opentelemetry.instrumentation.django.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.metric import (
- HTTPMetricRecorder,
- HTTPMetricType,
- MetricMixin,
-)
-
-_logger = getLogger(__name__)
-
-
-class DjangoInstrumentor(BaseInstrumentor, MetricMixin):
- """An instrumentor for Django
-
- See `BaseInstrumentor`
- """
-
- _opentelemetry_middleware = ".".join(
- [_DjangoMiddleware.__module__, _DjangoMiddleware.__qualname__]
- )
-
- def _instrument(self, **kwargs):
-
- # FIXME this is probably a pattern that will show up in the rest of the
- # ext. Find a better way of implementing this.
- # FIXME Probably the evaluation of strings into boolean values can be
- # built inside the Configuration class itself with the magic method
- # __bool__
-
- if Configuration().DJANGO_INSTRUMENT is False:
- return
-
- # This can not be solved, but is an inherent problem of this approach:
- # the order of middleware entries matters, and here you have no control
- # on that:
- # https://docs.djangoproject.com/en/3.0/topics/http/middleware/#activating-middleware
- # https://docs.djangoproject.com/en/3.0/ref/middleware/#middleware-ordering
-
- settings_middleware = getattr(settings, "MIDDLEWARE", [])
- # Django allows to specify middlewares as a tuple, so we convert this tuple to a
- # list, otherwise we wouldn't be able to call append/remove
- if isinstance(settings_middleware, tuple):
- settings_middleware = list(settings_middleware)
-
- settings_middleware.insert(0, self._opentelemetry_middleware)
- self.init_metrics(
- __name__, __version__,
- )
- metric_recorder = HTTPMetricRecorder(self.meter, HTTPMetricType.SERVER)
- setattr(settings, "OTEL_METRIC_RECORDER", metric_recorder)
- setattr(settings, "MIDDLEWARE", settings_middleware)
-
- def _uninstrument(self, **kwargs):
- settings_middleware = getattr(settings, "MIDDLEWARE", None)
-
- # FIXME This is starting to smell like trouble. We have 2 mechanisms
- # that may make this condition be True, one implemented in
- # BaseInstrumentor and another one implemented in _instrument. Both
- # stop _instrument from running and thus, settings_middleware not being
- # set.
- if settings_middleware is None or (
- self._opentelemetry_middleware not in settings_middleware
- ):
- return
-
- settings_middleware.remove(self._opentelemetry_middleware)
- setattr(settings, "MIDDLEWARE", settings_middleware)
diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py
deleted file mode 100644
index 1f465ca57a7..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py
+++ /dev/null
@@ -1,232 +0,0 @@
-# Copyright The OpenTelemetry 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 time
-from logging import getLogger
-
-from django.conf import settings
-
-from opentelemetry.configuration import Configuration
-from opentelemetry.context import attach, detach
-from opentelemetry.instrumentation.django.version import __version__
-from opentelemetry.instrumentation.utils import extract_attributes_from_object
-from opentelemetry.instrumentation.wsgi import (
- add_response_attributes,
- carrier_getter,
- collect_request_attributes,
-)
-from opentelemetry.propagators import extract
-from opentelemetry.trace import SpanKind, get_tracer
-from opentelemetry.util import ExcludeList
-
-try:
- from django.core.urlresolvers import ( # pylint: disable=no-name-in-module
- resolve,
- Resolver404,
- )
-except ImportError:
- from django.urls import resolve, Resolver404
-
-try:
- from django.utils.deprecation import MiddlewareMixin
-except ImportError:
- MiddlewareMixin = object
-
-_logger = getLogger(__name__)
-_attributes_by_preference = [
- ["http.scheme", "http.host", "http.target"],
- ["http.scheme", "http.server_name", "net.host.port", "http.target"],
- ["http.scheme", "net.host.name", "net.host.port", "http.target"],
- ["http.url"],
-]
-
-
-class _DjangoMiddleware(MiddlewareMixin):
- """Django Middleware for OpenTelemetry"""
-
- _environ_activation_key = (
- "opentelemetry-instrumentor-django.activation_key"
- )
- _environ_token = "opentelemetry-instrumentor-django.token"
- _environ_span_key = "opentelemetry-instrumentor-django.span_key"
- _environ_exception_key = "opentelemetry-instrumentor-django.exception_key"
-
- _excluded_urls = Configuration().DJANGO_EXCLUDED_URLS or []
- if _excluded_urls:
- _excluded_urls = ExcludeList(str.split(_excluded_urls, ","))
- else:
- _excluded_urls = ExcludeList(_excluded_urls)
-
- _traced_request_attrs = [
- attr.strip()
- for attr in (Configuration().DJANGO_TRACED_REQUEST_ATTRS or "").split(
- ","
- )
- ]
-
- @staticmethod
- def _get_span_name(request):
- try:
- if getattr(request, "resolver_match"):
- match = request.resolver_match
- else:
- match = resolve(request.path)
-
- if hasattr(match, "route"):
- return match.route
-
- # Instead of using `view_name`, better to use `_func_name` as some applications can use similar
- # view names in different modules
- if hasattr(match, "_func_name"):
- return match._func_name # pylint: disable=protected-access
-
- # Fallback for safety as `_func_name` private field
- return match.view_name
-
- except Resolver404:
- return "HTTP {}".format(request.method)
-
- @staticmethod
- def _get_metric_labels_from_attributes(attributes):
- labels = {}
- labels["http.method"] = attributes.get("http.method", "")
- for attrs in _attributes_by_preference:
- labels_from_attributes = {
- attr: attributes.get(attr, None) for attr in attrs
- }
- if set(attrs).issubset(attributes.keys()):
- labels.update(labels_from_attributes)
- break
- if attributes.get("http.flavor"):
- labels["http.flavor"] = attributes.get("http.flavor")
- return labels
-
- def process_request(self, request):
- # request.META is a dictionary containing all available HTTP headers
- # Read more about request.META here:
- # https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest.META
-
- if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
- return
-
- # pylint:disable=W0212
- request._otel_start_time = time.time()
-
- environ = request.META
-
- token = attach(extract(carrier_getter, environ))
-
- tracer = get_tracer(__name__, __version__)
-
- span = tracer.start_span(
- self._get_span_name(request),
- kind=SpanKind.SERVER,
- start_time=environ.get(
- "opentelemetry-instrumentor-django.starttime_key"
- ),
- )
-
- attributes = collect_request_attributes(environ)
- # pylint:disable=W0212
- request._otel_labels = self._get_metric_labels_from_attributes(
- attributes
- )
-
- if span.is_recording():
- attributes = extract_attributes_from_object(
- request, self._traced_request_attrs, attributes
- )
- for key, value in attributes.items():
- span.set_attribute(key, value)
-
- activation = tracer.use_span(span, end_on_exit=True)
- activation.__enter__()
-
- request.META[self._environ_activation_key] = activation
- request.META[self._environ_span_key] = span
- request.META[self._environ_token] = token
-
- # pylint: disable=unused-argument
- def process_view(self, request, view_func, *args, **kwargs):
- # Process view is executed before the view function, here we get the
- # route template from request.resolver_match. It is not set yet in process_request
- if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
- return
-
- if (
- self._environ_activation_key in request.META.keys()
- and self._environ_span_key in request.META.keys()
- ):
- span = request.META[self._environ_span_key]
-
- if span.is_recording():
- match = getattr(request, "resolver_match")
- if match:
- route = getattr(match, "route")
- if route:
- span.set_attribute("http.route", route)
-
- def process_exception(self, request, exception):
- if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
- return
-
- if self._environ_activation_key in request.META.keys():
- request.META[self._environ_exception_key] = exception
-
- def process_response(self, request, response):
- if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
- return response
-
- if (
- self._environ_activation_key in request.META.keys()
- and self._environ_span_key in request.META.keys()
- ):
- add_response_attributes(
- request.META[self._environ_span_key],
- "{} {}".format(response.status_code, response.reason_phrase),
- response,
- )
- # pylint:disable=W0212
- request._otel_labels["http.status_code"] = str(
- response.status_code
- )
- request.META.pop(self._environ_span_key)
-
- exception = request.META.pop(self._environ_exception_key, None)
- if exception:
- request.META[self._environ_activation_key].__exit__(
- type(exception),
- exception,
- getattr(exception, "__traceback__", None),
- )
- else:
- request.META[self._environ_activation_key].__exit__(
- None, None, None
- )
- request.META.pop(self._environ_activation_key)
-
- if self._environ_token in request.META.keys():
- detach(request.environ.get(self._environ_token))
- request.META.pop(self._environ_token)
-
- try:
- metric_recorder = getattr(settings, "OTEL_METRIC_RECORDER", None)
- if metric_recorder is not None:
- # pylint:disable=W0212
- metric_recorder.record_server_duration_range(
- request._otel_start_time, time.time(), request._otel_labels
- )
- except Exception as ex: # pylint: disable=W0703
- _logger.warning("Error recording duration metrics: %s", ex)
- return response
diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/version.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-django/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py
deleted file mode 100644
index 3f70f62bec0..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py
+++ /dev/null
@@ -1,315 +0,0 @@
-# Copyright The OpenTelemetry 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 sys import modules
-from unittest.mock import Mock, patch
-
-from django import VERSION
-from django.conf import settings
-from django.conf.urls import url
-from django.test import Client
-from django.test.utils import setup_test_environment, teardown_test_environment
-
-from opentelemetry.configuration import Configuration
-from opentelemetry.instrumentation.django import DjangoInstrumentor
-from opentelemetry.sdk.util import get_dict_as_key
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.test.wsgitestutil import WsgiTestBase
-from opentelemetry.trace import SpanKind
-from opentelemetry.trace.status import StatusCode
-from opentelemetry.util import ExcludeList
-
-# pylint: disable=import-error
-from .views import (
- error,
- excluded,
- excluded_noarg,
- excluded_noarg2,
- route_span_name,
- traced,
- traced_template,
-)
-
-DJANGO_2_2 = VERSION >= (2, 2)
-
-urlpatterns = [
- url(r"^traced/", traced),
- url(r"^route/(?P[0-9]{4})/template/$", traced_template),
- url(r"^error/", error),
- url(r"^excluded_arg/", excluded),
- url(r"^excluded_noarg/", excluded_noarg),
- url(r"^excluded_noarg2/", excluded_noarg2),
- url(r"^span_name/([0-9]{4})/$", route_span_name),
-]
-_django_instrumentor = DjangoInstrumentor()
-
-
-class TestMiddleware(TestBase, WsgiTestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- settings.configure(ROOT_URLCONF=modules[__name__])
-
- def setUp(self):
- super().setUp()
- setup_test_environment()
- _django_instrumentor.instrument()
- Configuration._reset() # pylint: disable=protected-access
-
- def tearDown(self):
- super().tearDown()
- teardown_test_environment()
- _django_instrumentor.uninstrument()
-
- def test_templated_route_get(self):
- Client().get("/route/2020/template/")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
-
- span = spans[0]
-
- self.assertEqual(
- span.name,
- "^route/(?P[0-9]{4})/template/$"
- if DJANGO_2_2
- else "tests.views.traced",
- )
- self.assertEqual(span.kind, SpanKind.SERVER)
- self.assertEqual(span.status.status_code, StatusCode.UNSET)
- self.assertEqual(span.attributes["http.method"], "GET")
- self.assertEqual(
- span.attributes["http.url"],
- "http://testserver/route/2020/template/",
- )
- self.assertEqual(
- span.attributes["http.route"],
- "^route/(?P[0-9]{4})/template/$",
- )
- self.assertEqual(span.attributes["http.scheme"], "http")
- self.assertEqual(span.attributes["http.status_code"], 200)
- self.assertEqual(span.attributes["http.status_text"], "OK")
-
- def test_traced_get(self):
- Client().get("/traced/")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
-
- span = spans[0]
-
- self.assertEqual(
- span.name, "^traced/" if DJANGO_2_2 else "tests.views.traced"
- )
- self.assertEqual(span.kind, SpanKind.SERVER)
- self.assertEqual(span.status.status_code, StatusCode.UNSET)
- self.assertEqual(span.attributes["http.method"], "GET")
- self.assertEqual(
- span.attributes["http.url"], "http://testserver/traced/"
- )
- self.assertEqual(span.attributes["http.route"], "^traced/")
- self.assertEqual(span.attributes["http.scheme"], "http")
- self.assertEqual(span.attributes["http.status_code"], 200)
- self.assertEqual(span.attributes["http.status_text"], "OK")
-
- self.assertIsNotNone(_django_instrumentor.meter)
- self.assertEqual(len(_django_instrumentor.meter.metrics), 1)
- recorder = _django_instrumentor.meter.metrics.pop()
- match_key = get_dict_as_key(
- {
- "http.flavor": "1.1",
- "http.method": "GET",
- "http.status_code": "200",
- "http.url": "http://testserver/traced/",
- }
- )
- for key in recorder.bound_instruments.keys():
- self.assertEqual(key, match_key)
- # pylint: disable=protected-access
- bound = recorder.bound_instruments.get(key)
- for view_data in bound.view_datas:
- self.assertEqual(view_data.labels, key)
- self.assertEqual(view_data.aggregator.current.count, 1)
- self.assertGreaterEqual(view_data.aggregator.current.sum, 0)
-
- def test_not_recording(self):
- mock_tracer = Mock()
- mock_span = Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- with patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- Client().get("/traced/")
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_traced_post(self):
- Client().post("/traced/")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
-
- span = spans[0]
-
- self.assertEqual(
- span.name, "^traced/" if DJANGO_2_2 else "tests.views.traced"
- )
- self.assertEqual(span.kind, SpanKind.SERVER)
- self.assertEqual(span.status.status_code, StatusCode.UNSET)
- self.assertEqual(span.attributes["http.method"], "POST")
- self.assertEqual(
- span.attributes["http.url"], "http://testserver/traced/"
- )
- self.assertEqual(span.attributes["http.route"], "^traced/")
- self.assertEqual(span.attributes["http.scheme"], "http")
- self.assertEqual(span.attributes["http.status_code"], 200)
- self.assertEqual(span.attributes["http.status_text"], "OK")
-
- def test_error(self):
- with self.assertRaises(ValueError):
- Client().get("/error/")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
-
- span = spans[0]
-
- self.assertEqual(
- span.name, "^error/" if DJANGO_2_2 else "tests.views.error"
- )
- self.assertEqual(span.kind, SpanKind.SERVER)
- self.assertEqual(span.status.status_code, StatusCode.ERROR)
- self.assertEqual(span.attributes["http.method"], "GET")
- self.assertEqual(
- span.attributes["http.url"], "http://testserver/error/"
- )
- self.assertEqual(span.attributes["http.route"], "^error/")
- self.assertEqual(span.attributes["http.scheme"], "http")
- self.assertEqual(span.attributes["http.status_code"], 500)
- self.assertIsNotNone(_django_instrumentor.meter)
- self.assertEqual(len(_django_instrumentor.meter.metrics), 1)
-
- self.assertEqual(len(span.events), 1)
- event = span.events[0]
- self.assertEqual(event.name, "exception")
- self.assertEqual(event.attributes["exception.type"], "ValueError")
- self.assertEqual(event.attributes["exception.message"], "error")
-
- recorder = _django_instrumentor.meter.metrics.pop()
- match_key = get_dict_as_key(
- {
- "http.flavor": "1.1",
- "http.method": "GET",
- "http.status_code": "500",
- "http.url": "http://testserver/error/",
- }
- )
- for key in recorder.bound_instruments.keys():
- self.assertEqual(key, match_key)
- # pylint: disable=protected-access
- bound = recorder.bound_instruments.get(key)
- for view_data in bound.view_datas:
- self.assertEqual(view_data.labels, key)
- self.assertEqual(view_data.aggregator.current.count, 1)
-
- @patch(
- "opentelemetry.instrumentation.django.middleware._DjangoMiddleware._excluded_urls",
- ExcludeList(["http://testserver/excluded_arg/123", "excluded_noarg"]),
- )
- def test_exclude_lists(self):
- client = Client()
- client.get("/excluded_arg/123")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 0)
-
- client.get("/excluded_arg/125")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- client.get("/excluded_noarg/")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- client.get("/excluded_noarg2/")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- def test_span_name(self):
- # test no query_string
- Client().get("/span_name/1234/")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- span = span_list[0]
- self.assertEqual(
- span.name,
- "^span_name/([0-9]{4})/$"
- if DJANGO_2_2
- else "tests.views.route_span_name",
- )
-
- def test_span_name_for_query_string(self):
- """
- request not have query string
- """
- Client().get("/span_name/1234/?query=test")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- span = span_list[0]
- self.assertEqual(
- span.name,
- "^span_name/([0-9]{4})/$"
- if DJANGO_2_2
- else "tests.views.route_span_name",
- )
-
- def test_span_name_404(self):
- Client().get("/span_name/1234567890/")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- span = span_list[0]
- self.assertEqual(span.name, "HTTP GET")
-
- def test_traced_request_attrs(self):
- with patch(
- "opentelemetry.instrumentation.django.middleware._DjangoMiddleware._traced_request_attrs",
- [],
- ):
- Client().get("/span_name/1234/", CONTENT_TYPE="test/ct")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- span = span_list[0]
- self.assertNotIn("path_info", span.attributes)
- self.assertNotIn("content_type", span.attributes)
- self.memory_exporter.clear()
-
- with patch(
- "opentelemetry.instrumentation.django.middleware._DjangoMiddleware._traced_request_attrs",
- ["path_info", "content_type", "non_existing_variable"],
- ):
- Client().get("/span_name/1234/", CONTENT_TYPE="test/ct")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- span = span_list[0]
- self.assertEqual(span.attributes["path_info"], "/span_name/1234/")
- self.assertEqual(span.attributes["content_type"], "test/ct")
- self.assertNotIn("non_existing_variable", span.attributes)
diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/views.py b/instrumentation/opentelemetry-instrumentation-django/tests/views.py
deleted file mode 100644
index 872222a8422..00000000000
--- a/instrumentation/opentelemetry-instrumentation-django/tests/views.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from django.http import HttpResponse
-
-
-def traced(request): # pylint: disable=unused-argument
- return HttpResponse()
-
-
-def traced_template(request, year): # pylint: disable=unused-argument
- return HttpResponse()
-
-
-def error(request): # pylint: disable=unused-argument
- raise ValueError("error")
-
-
-def excluded(request): # pylint: disable=unused-argument
- return HttpResponse()
-
-
-def excluded_noarg(request): # pylint: disable=unused-argument
- return HttpResponse()
-
-
-def excluded_noarg2(request): # pylint: disable=unused-argument
- return HttpResponse()
-
-
-def route_span_name(
- request, *args, **kwargs
-): # pylint: disable=unused-argument
- return HttpResponse()
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-elasticsearch/CHANGELOG.md
deleted file mode 100644
index f07f5140233..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/CHANGELOG.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Update environment variable names, prefix changed from `OPENTELEMETRY` to `OTEL` ([#904](https://github.com/open-telemetry/opentelemetry-python/pull/904))
-- Change package name to opentelemetry-instrumentation-elasticsearch
- ([#969](https://github.com/open-telemetry/opentelemetry-python/pull/969))
-
-## Version 0.10b0
-
-Released 2020-06-23
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/LICENSE b/instrumentation/opentelemetry-instrumentation-elasticsearch/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-elasticsearch/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-elasticsearch/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/README.rst b/instrumentation/opentelemetry-instrumentation-elasticsearch/README.rst
deleted file mode 100644
index 9f898e78358..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/README.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-OpenTelemetry elasticsearch Integration
-========================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-elasticsearch.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-elasticsearch/
-
-This library allows tracing elasticsearch made by the
-`elasticsearch `_ library.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-elasticsearch
-
-References
-----------
-
-* `OpenTelemetry elasticsearch Integration `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.cfg b/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.cfg
deleted file mode 100644
index b1ebcfe76ad..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.cfg
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-elasticsearch
-description = OpenTelemetry elasticsearch instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-elasticsearch
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- wrapt >= 1.0.0, < 2.0.0
- elasticsearch >= 2.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
- elasticsearch-dsl >= 2.0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- elasticsearch = opentelemetry.instrumentation.elasticsearch:ElasticsearchInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.py
deleted file mode 100644
index cd7a7f10129..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "elasticsearch",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py
deleted file mode 100644
index 541cdbfa6e3..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-This library allows tracing HTTP elasticsearch made by the
-`elasticsearch `_ library.
-
-Usage
------
-
-.. code-block:: python
-
- from opentelemetry import trace
- from opentelemetry.instrumentation.elasticsearch import ElasticSearchInstrumentor
- from opentelemetry.sdk.trace import TracerProvider
- import elasticsearch
-
- trace.set_tracer_provider(TracerProvider())
-
- # instrument elasticsearch
- ElasticSearchInstrumentor().instrument(tracer_provider=trace.get_tracer_provider())
-
- # Using elasticsearch as normal now will automatically generate spans
- es = elasticsearch.Elasticsearch()
- es.index(index='my-index', doc_type='my-type', id=1, body={'my': 'data', 'timestamp': datetime.now()})
- es.get(index='my-index', doc_type='my-type', id=1)
-
-API
----
-
-Elasticsearch instrumentation prefixes operation names with the string "Elasticsearch". This
-can be changed to a different string by either setting the `OTEL_PYTHON_ELASTICSEARCH_NAME_PREFIX`
-environment variable or by passing the prefix as an argument to the instrumentor. For example,
-
-
-.. code-block:: python
-
- ElasticSearchInstrumentor("my-custom-prefix").instrument()
-"""
-
-import functools
-import types
-from logging import getLogger
-from os import environ
-
-import elasticsearch
-import elasticsearch.exceptions
-from wrapt import ObjectProxy
-from wrapt import wrap_function_wrapper as _wrap
-
-from opentelemetry import context, propagators, trace
-from opentelemetry.instrumentation.elasticsearch.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.utils import unwrap
-from opentelemetry.trace import SpanKind, get_tracer
-from opentelemetry.trace.status import Status, StatusCode
-
-logger = getLogger(__name__)
-
-
-# Values to add as tags from the actual
-# payload returned by Elasticsearch, if any.
-_ATTRIBUTES_FROM_RESULT = [
- "found",
- "timed_out",
- "took",
-]
-
-_DEFALT_OP_NAME = "request"
-
-
-class ElasticsearchInstrumentor(BaseInstrumentor):
- """An instrumentor for elasticsearch
- See `BaseInstrumentor`
- """
-
- def __init__(self, span_name_prefix=None):
- if not span_name_prefix:
- span_name_prefix = environ.get(
- "OTEL_PYTHON_ELASTICSEARCH_NAME_PREFIX", "Elasticsearch",
- )
- self._span_name_prefix = span_name_prefix.strip()
- super().__init__()
-
- def _instrument(self, **kwargs):
- """
- Instruments elasticsarch module
- """
- tracer_provider = kwargs.get("tracer_provider")
- tracer = get_tracer(__name__, __version__, tracer_provider)
- _wrap(
- elasticsearch,
- "Transport.perform_request",
- _wrap_perform_request(tracer, self._span_name_prefix),
- )
-
- def _uninstrument(self, **kwargs):
- unwrap(elasticsearch.Transport, "perform_request")
-
-
-def _wrap_perform_request(tracer, span_name_prefix):
- # pylint: disable=R0912
- def wrapper(wrapped, _, args, kwargs):
- method = url = None
- try:
- method, url, *_ = args
- except IndexError:
- logger.warning(
- "expected perform_request to receive two positional arguments. "
- "Got %d",
- len(args),
- )
-
- op_name = span_name_prefix + (url or method or _DEFALT_OP_NAME)
- params = kwargs.get("params", {})
- body = kwargs.get("body", None)
-
- with tracer.start_as_current_span(
- op_name, kind=SpanKind.CLIENT,
- ) as span:
- if span.is_recording():
- attributes = {
- "component": "elasticsearch-py",
- "db.type": "elasticsearch",
- }
- if url:
- attributes["elasticsearch.url"] = url
- if method:
- attributes["elasticsearch.method"] = method
- if body:
- attributes["db.statement"] = str(body)
- if params:
- attributes["elasticsearch.params"] = str(params)
- for key, value in attributes.items():
- span.set_attribute(key, value)
- try:
- rv = wrapped(*args, **kwargs)
- if isinstance(rv, dict) and span.is_recording():
- for member in _ATTRIBUTES_FROM_RESULT:
- if member in rv:
- span.set_attribute(
- "elasticsearch.{0}".format(member),
- str(rv[member]),
- )
- return rv
- except Exception as ex: # pylint: disable=broad-except
- if span.is_recording():
- span.set_status(Status(StatusCode.ERROR, str(ex)))
- raise ex
-
- return wrapper
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/version.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es2.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es2.py
deleted file mode 100644
index 008a95d6716..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es2.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from elasticsearch_dsl import ( # pylint: disable=no-name-in-module
- DocType,
- String,
-)
-
-
-class Article(DocType):
- title = String(analyzer="snowball", fields={"raw": String()})
- body = String(analyzer="snowball")
-
- class Meta:
- index = "test-index"
-
-
-dsl_create_statement = {
- "mappings": {
- "article": {
- "properties": {
- "title": {
- "analyzer": "snowball",
- "fields": {"raw": {"type": "string"}},
- "type": "string",
- },
- "body": {"analyzer": "snowball", "type": "string"},
- }
- }
- },
- "settings": {"analysis": {}},
-}
-dsl_index_result = (1, {}, '{"created": true}')
-dsl_index_span_name = "Elasticsearch/test-index/article/2"
-dsl_index_url = "/test-index/article/2"
-dsl_search_method = "GET"
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es5.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es5.py
deleted file mode 100644
index cf32d988635..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es5.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from elasticsearch_dsl import ( # pylint: disable=no-name-in-module
- DocType,
- Keyword,
- Text,
-)
-
-
-class Article(DocType):
- title = Text(analyzer="snowball", fields={"raw": Keyword()})
- body = Text(analyzer="snowball")
-
- class Meta:
- index = "test-index"
-
-
-dsl_create_statement = {
- "mappings": {
- "article": {
- "properties": {
- "title": {
- "analyzer": "snowball",
- "fields": {"raw": {"type": "keyword"}},
- "type": "text",
- },
- "body": {"analyzer": "snowball", "type": "text"},
- }
- }
- },
-}
-dsl_index_result = (1, {}, '{"created": true}')
-dsl_index_span_name = "Elasticsearch/test-index/article/2"
-dsl_index_url = "/test-index/article/2"
-dsl_search_method = "GET"
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es6.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es6.py
deleted file mode 100644
index b27d291ba3f..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es6.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from elasticsearch_dsl import ( # pylint: disable=unused-import
- Document,
- Keyword,
- Text,
-)
-
-
-class Article(Document):
- title = Text(analyzer="snowball", fields={"raw": Keyword()})
- body = Text(analyzer="snowball")
-
- class Index:
- name = "test-index"
-
-
-dsl_create_statement = {
- "mappings": {
- "doc": {
- "properties": {
- "title": {
- "analyzer": "snowball",
- "fields": {"raw": {"type": "keyword"}},
- "type": "text",
- },
- "body": {"analyzer": "snowball", "type": "text"},
- }
- }
- }
-}
-dsl_index_result = (1, {}, '{"result": "created"}')
-dsl_index_span_name = "Elasticsearch/test-index/doc/2"
-dsl_index_url = "/test-index/doc/2"
-dsl_search_method = "GET"
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es7.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es7.py
deleted file mode 100644
index a2d37a54a9a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/helpers_es7.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from elasticsearch_dsl import ( # pylint: disable=unused-import
- Document,
- Keyword,
- Text,
-)
-
-
-class Article(Document):
- title = Text(analyzer="snowball", fields={"raw": Keyword()})
- body = Text(analyzer="snowball")
-
- class Index:
- name = "test-index"
-
-
-dsl_create_statement = {
- "mappings": {
- "properties": {
- "title": {
- "analyzer": "snowball",
- "fields": {"raw": {"type": "keyword"}},
- "type": "text",
- },
- "body": {"analyzer": "snowball", "type": "text"},
- }
- }
-}
-dsl_index_result = (1, {}, '{"result": "created"}')
-dsl_index_span_name = "Elasticsearch/test-index/_doc/2"
-dsl_index_url = "/test-index/_doc/2"
-dsl_search_method = "POST"
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py
deleted file mode 100644
index ea0e6ce2fbf..00000000000
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py
+++ /dev/null
@@ -1,327 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-import threading
-from ast import literal_eval
-from unittest import mock
-
-import elasticsearch
-import elasticsearch.exceptions
-from elasticsearch import Elasticsearch
-from elasticsearch_dsl import Search
-
-import opentelemetry.instrumentation.elasticsearch
-from opentelemetry.instrumentation.elasticsearch import (
- ElasticsearchInstrumentor,
-)
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace.status import StatusCode
-
-major_version = elasticsearch.VERSION[0]
-
-if major_version == 7:
- from . import helpers_es7 as helpers # pylint: disable=no-name-in-module
-elif major_version == 6:
- from . import helpers_es6 as helpers # pylint: disable=no-name-in-module
-elif major_version == 5:
- from . import helpers_es5 as helpers # pylint: disable=no-name-in-module
-else:
- from . import helpers_es2 as helpers # pylint: disable=no-name-in-module
-
-
-Article = helpers.Article
-
-
-@mock.patch(
- "elasticsearch.connection.http_urllib3.Urllib3HttpConnection.perform_request"
-)
-class TestElasticsearchIntegration(TestBase):
- def setUp(self):
- super().setUp()
- self.tracer = self.tracer_provider.get_tracer(__name__)
- ElasticsearchInstrumentor().instrument()
-
- def tearDown(self):
- super().tearDown()
- with self.disable_logging():
- ElasticsearchInstrumentor().uninstrument()
-
- def get_ordered_finished_spans(self):
- return sorted(
- self.memory_exporter.get_finished_spans(),
- key=lambda s: s.start_time,
- )
-
- def test_instrumentor(self, request_mock):
- request_mock.return_value = (1, {}, {})
-
- es = Elasticsearch()
- es.index(index="sw", doc_type="people", id=1, body={"name": "adam"})
-
- spans_list = self.get_ordered_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- # Check version and name in span's instrumentation info
- # self.check_span_instrumentation_info(span, opentelemetry.instrumentation.elasticsearch)
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.elasticsearch
- )
-
- # check that no spans are generated after uninstrument
- ElasticsearchInstrumentor().uninstrument()
-
- es.index(index="sw", doc_type="people", id=1, body={"name": "adam"})
-
- spans_list = self.get_ordered_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- def test_span_not_recording(self, request_mock):
- request_mock.return_value = (1, {}, {})
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = mock_span
- with mock.patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- Elasticsearch()
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- ElasticsearchInstrumentor().uninstrument()
-
- def test_prefix_arg(self, request_mock):
- prefix = "prefix-from-env"
- ElasticsearchInstrumentor().uninstrument()
- ElasticsearchInstrumentor(span_name_prefix=prefix).instrument()
- request_mock.return_value = (1, {}, {})
- self._test_prefix(prefix)
-
- def test_prefix_env(self, request_mock):
- prefix = "prefix-from-args"
- env_var = "OTEL_PYTHON_ELASTICSEARCH_NAME_PREFIX"
- os.environ[env_var] = prefix
- ElasticsearchInstrumentor().uninstrument()
- ElasticsearchInstrumentor().instrument()
- request_mock.return_value = (1, {}, {})
- del os.environ[env_var]
- self._test_prefix(prefix)
-
- def _test_prefix(self, prefix):
- es = Elasticsearch()
- es.index(index="sw", doc_type="people", id=1, body={"name": "adam"})
-
- spans_list = self.get_ordered_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertTrue(span.name.startswith(prefix))
-
- def test_result_values(self, request_mock):
- request_mock.return_value = (
- 1,
- {},
- '{"found": false, "timed_out": true, "took": 7}',
- )
- es = Elasticsearch()
- es.get(index="test-index", doc_type="tweet", id=1)
-
- spans = self.get_ordered_finished_spans()
-
- self.assertEqual(1, len(spans))
- self.assertEqual("False", spans[0].attributes["elasticsearch.found"])
- self.assertEqual(
- "True", spans[0].attributes["elasticsearch.timed_out"]
- )
- self.assertEqual("7", spans[0].attributes["elasticsearch.took"])
-
- def test_trace_error_unknown(self, request_mock):
- exc = RuntimeError("custom error")
- request_mock.side_effect = exc
- self._test_trace_error(StatusCode.ERROR, exc)
-
- def test_trace_error_not_found(self, request_mock):
- msg = "record not found"
- exc = elasticsearch.exceptions.NotFoundError(404, msg)
- request_mock.return_value = (1, {}, {})
- request_mock.side_effect = exc
- self._test_trace_error(StatusCode.ERROR, exc)
-
- def _test_trace_error(self, code, exc):
- es = Elasticsearch()
- try:
- es.get(index="test-index", doc_type="tweet", id=1)
- except Exception: # pylint: disable=broad-except
- pass
-
- spans = self.get_ordered_finished_spans()
- self.assertEqual(1, len(spans))
- span = spans[0]
- self.assertFalse(span.status.is_ok)
- self.assertEqual(span.status.status_code, code)
- self.assertEqual(span.status.description, str(exc))
-
- def test_parent(self, request_mock):
- request_mock.return_value = (1, {}, {})
- es = Elasticsearch()
- with self.tracer.start_as_current_span("parent"):
- es.index(
- index="sw", doc_type="people", id=1, body={"name": "adam"}
- )
-
- spans = self.get_ordered_finished_spans()
- self.assertEqual(len(spans), 2)
-
- self.assertEqual(spans[0].name, "parent")
- self.assertEqual(spans[1].name, "Elasticsearch/sw/people/1")
- self.assertIsNotNone(spans[1].parent)
- self.assertEqual(spans[1].parent.span_id, spans[0].context.span_id)
-
- def test_multithread(self, request_mock):
- request_mock.return_value = (1, {}, {})
- es = Elasticsearch()
- ev = threading.Event()
-
- # 1. Start tracing from thread-1; make thread-2 wait
- # 2. Trace something from thread-2, make thread-1 join before finishing.
- # 3. Check the spans got different parents, and are in the expected order.
- def target1(parent_span):
- with self.tracer.use_span(parent_span):
- es.get(index="test-index", doc_type="tweet", id=1)
- ev.set()
- ev.wait()
-
- def target2():
- ev.wait()
- es.get(index="test-index", doc_type="tweet", id=2)
- ev.set()
-
- with self.tracer.start_as_current_span("parent") as span:
- t1 = threading.Thread(target=target1, args=(span,))
- t1.start()
-
- t2 = threading.Thread(target=target2)
- t2.start()
- t1.join()
- t2.join()
-
- spans = self.get_ordered_finished_spans()
- self.assertEqual(3, len(spans))
- s1, s2, s3 = spans
-
- self.assertEqual(s1.name, "parent")
-
- self.assertEqual(s2.name, "Elasticsearch/test-index/tweet/1")
- self.assertIsNotNone(s2.parent)
- self.assertEqual(s2.parent.span_id, s1.context.span_id)
- self.assertEqual(s3.name, "Elasticsearch/test-index/tweet/2")
- self.assertIsNone(s3.parent)
-
- def test_dsl_search(self, request_mock):
- request_mock.return_value = (1, {}, '{"hits": {"hits": []}}')
-
- client = Elasticsearch()
- search = Search(using=client, index="test-index").filter(
- "term", author="testing"
- )
- search.execute()
- spans = self.get_ordered_finished_spans()
- span = spans[0]
- self.assertEqual(1, len(spans))
- self.assertEqual(span.name, "Elasticsearch/test-index/_search")
- self.assertIsNotNone(span.end_time)
- self.assertEqual(
- span.attributes,
- {
- "component": "elasticsearch-py",
- "db.type": "elasticsearch",
- "elasticsearch.url": "/test-index/_search",
- "elasticsearch.method": helpers.dsl_search_method,
- "db.statement": str(
- {
- "query": {
- "bool": {
- "filter": [{"term": {"author": "testing"}}]
- }
- }
- }
- ),
- },
- )
-
- def test_dsl_create(self, request_mock):
- request_mock.return_value = (1, {}, {})
- client = Elasticsearch()
- Article.init(using=client)
-
- spans = self.get_ordered_finished_spans()
- self.assertEqual(2, len(spans))
- span1, span2 = spans
- self.assertEqual(span1.name, "Elasticsearch/test-index")
- self.assertEqual(
- span1.attributes,
- {
- "component": "elasticsearch-py",
- "db.type": "elasticsearch",
- "elasticsearch.url": "/test-index",
- "elasticsearch.method": "HEAD",
- },
- )
-
- self.assertEqual(span2.name, "Elasticsearch/test-index")
- attributes = {
- "component": "elasticsearch-py",
- "db.type": "elasticsearch",
- "elasticsearch.url": "/test-index",
- "elasticsearch.method": "PUT",
- }
- self.assert_span_has_attributes(span2, attributes)
- self.assertEqual(
- literal_eval(span2.attributes["db.statement"]),
- helpers.dsl_create_statement,
- )
-
- def test_dsl_index(self, request_mock):
- request_mock.return_value = helpers.dsl_index_result
-
- client = Elasticsearch()
- article = Article(
- meta={"id": 2},
- title="About searching",
- body="A few words here, a few words there",
- )
- res = article.save(using=client)
- self.assertTrue(res)
- spans = self.get_ordered_finished_spans()
- self.assertEqual(1, len(spans))
- span = spans[0]
- self.assertEqual(span.name, helpers.dsl_index_span_name)
- attributes = {
- "component": "elasticsearch-py",
- "db.type": "elasticsearch",
- "elasticsearch.url": helpers.dsl_index_url,
- "elasticsearch.method": "PUT",
- }
- self.assert_span_has_attributes(span, attributes)
- self.assertEqual(
- literal_eval(span.attributes["db.statement"]),
- {
- "body": "A few words here, a few words there",
- "title": "About searching",
- },
- )
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-falcon/CHANGELOG.md
deleted file mode 100644
index 85dcb366d0b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/CHANGELOG.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.14b0
-
-Released 2020-10-13
-
-- Added support for `OTEL_PYTHON_FALCON_TRACED_REQUEST_ATTRS` ([#1158](https://github.com/open-telemetry/opentelemetry-python/pull/1158))
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Initial release. Added instrumentation for Falcon 2.0+
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/LICENSE b/instrumentation/opentelemetry-instrumentation-falcon/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-falcon/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-falcon/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/README.rst b/instrumentation/opentelemetry-instrumentation-falcon/README.rst
deleted file mode 100644
index 8230deaf764..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/README.rst
+++ /dev/null
@@ -1,53 +0,0 @@
-OpenTelemetry Falcon Tracing
-============================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-falcon.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-falcon/
-
-This library builds on the OpenTelemetry WSGI middleware to track web requests
-in Falcon applications.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-falcon
-
-Configuration
--------------
-
-Exclude lists
-*************
-To exclude certain URLs from being tracked, set the environment variable ``OTEL_PYTHON_FALCON_EXCLUDED_URLS`` with comma delimited regexes representing which URLs to exclude.
-
-For example,
-
-::
-
- export OTEL_PYTHON_FALCON_EXCLUDED_URLS="client/.*/info,healthcheck"
-
-will exclude requests such as ``https://site/client/123/info`` and ``https://site/xyz/healthcheck``.
-
-Request attributes
-********************
-To extract certain attributes from Falcon's request object and use them as span attributes, set the environment variable ``OTEL_PYTHON_FALCON_TRACED_REQUEST_ATTRS`` to a comma
-delimited list of request attribute names.
-
-For example,
-
-::
-
- export OTEL_PYTHON_FALCON_TRACED_REQUEST_ATTRS='query_string,uri_template'
-
-will extract path_info and content_type attributes from every traced request and add them as span attritbues.
-
-Falcon Request object reference: https://falcon.readthedocs.io/en/stable/api/request_and_response.html#id1
-
-References
-----------
-
-* `OpenTelemetry Falcon Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg b/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg
deleted file mode 100644
index 88e287c6071..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-falcon
-description = Falcon instrumentation for OpenTelemetry
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-falcon
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.4
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.4
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- falcon ~= 2.0
- opentelemetry-instrumentation-wsgi == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- opentelemetry-api == 0.16.dev0
-
-[options.extras_require]
-test =
- falcon ~= 2.0
- opentelemetry-test == 0.16.dev0
- parameterized == 0.7.4
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- falcon = opentelemetry.instrumentation.falcon:FalconInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/setup.py b/instrumentation/opentelemetry-instrumentation-falcon/setup.py
deleted file mode 100644
index eb61edde629..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "falcon", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py
deleted file mode 100644
index 55f8e98dcb1..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py
+++ /dev/null
@@ -1,222 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-This library builds on the OpenTelemetry WSGI middleware to track web requests
-in Falcon applications. In addition to opentelemetry-instrumentation-wsgi,
-it supports falcon-specific features such as:
-
-* The Falcon resource and method name is used as the Span name.
-* The ``falcon.resource`` Span attribute is set so the matched resource.
-* Error from Falcon resources are properly caught and recorded.
-
-Usage
------
-
-.. code-block:: python
-
- from falcon import API
- from opentelemetry.instrumentation.falcon import FalconInstrumentor
-
- FalconInstrumentor().instrument()
-
- app = falcon.API()
-
- class HelloWorldResource(object):
- def on_get(self, req, resp):
- resp.body = 'Hello World'
-
- app.add_route('/hello', HelloWorldResource())
-
-API
----
-"""
-
-import sys
-from logging import getLogger
-
-import falcon
-
-import opentelemetry.instrumentation.wsgi as otel_wsgi
-from opentelemetry import configuration, context, propagators, trace
-from opentelemetry.configuration import Configuration
-from opentelemetry.instrumentation.falcon.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.utils import (
- extract_attributes_from_object,
- http_status_to_status_code,
-)
-from opentelemetry.trace.status import Status
-from opentelemetry.util import ExcludeList, time_ns
-
-_logger = getLogger(__name__)
-
-_ENVIRON_STARTTIME_KEY = "opentelemetry-falcon.starttime_key"
-_ENVIRON_SPAN_KEY = "opentelemetry-falcon.span_key"
-_ENVIRON_ACTIVATION_KEY = "opentelemetry-falcon.activation_key"
-_ENVIRON_TOKEN = "opentelemetry-falcon.token"
-_ENVIRON_EXC = "opentelemetry-falcon.exc"
-
-
-def get_excluded_urls():
- urls = configuration.Configuration().FALCON_EXCLUDED_URLS or ""
- if urls:
- urls = str.split(urls, ",")
- return ExcludeList(urls)
-
-
-_excluded_urls = get_excluded_urls()
-
-
-class FalconInstrumentor(BaseInstrumentor):
- # pylint: disable=protected-access,attribute-defined-outside-init
- """An instrumentor for falcon.API
-
- See `BaseInstrumentor`
- """
-
- def _instrument(self, **kwargs):
- self._original_falcon_api = falcon.API
- falcon.API = _InstrumentedFalconAPI
-
- def _uninstrument(self, **kwargs):
- falcon.API = self._original_falcon_api
-
-
-class _InstrumentedFalconAPI(falcon.API):
- def __init__(self, *args, **kwargs):
- middlewares = kwargs.pop("middleware", [])
- if not isinstance(middlewares, (list, tuple)):
- middlewares = [middlewares]
-
- self._tracer = trace.get_tracer(__name__, __version__)
- trace_middleware = _TraceMiddleware(
- self._tracer, kwargs.get("traced_request_attributes")
- )
- middlewares.insert(0, trace_middleware)
- kwargs["middleware"] = middlewares
- super().__init__(*args, **kwargs)
-
- def __call__(self, env, start_response):
- if _excluded_urls.url_disabled(env.get("PATH_INFO", "/")):
- return super().__call__(env, start_response)
-
- start_time = time_ns()
-
- token = context.attach(
- propagators.extract(otel_wsgi.carrier_getter, env)
- )
- span = self._tracer.start_span(
- otel_wsgi.get_default_span_name(env),
- kind=trace.SpanKind.SERVER,
- start_time=start_time,
- )
- if span.is_recording():
- attributes = otel_wsgi.collect_request_attributes(env)
- for key, value in attributes.items():
- span.set_attribute(key, value)
-
- activation = self._tracer.use_span(span, end_on_exit=True)
- activation.__enter__()
- env[_ENVIRON_SPAN_KEY] = span
- env[_ENVIRON_ACTIVATION_KEY] = activation
-
- def _start_response(status, response_headers, *args, **kwargs):
- otel_wsgi.add_response_attributes(span, status, response_headers)
- response = start_response(
- status, response_headers, *args, **kwargs
- )
- activation.__exit__(None, None, None)
- context.detach(token)
- return response
-
- try:
- return super().__call__(env, _start_response)
- except Exception as exc:
- activation.__exit__(
- type(exc), exc, getattr(exc, "__traceback__", None),
- )
- context.detach(token)
- raise
-
-
-class _TraceMiddleware:
- # pylint:disable=R0201,W0613
-
- def __init__(self, tracer=None, traced_request_attrs=None):
- self.tracer = tracer
- self._traced_request_attrs = traced_request_attrs or [
- attr.strip()
- for attr in (
- Configuration().FALCON_TRACED_REQUEST_ATTRS or ""
- ).split(",")
- ]
-
- def process_request(self, req, resp):
- span = req.env.get(_ENVIRON_SPAN_KEY)
- if not span or not span.is_recording():
- return
-
- attributes = extract_attributes_from_object(
- req, self._traced_request_attrs
- )
- for key, value in attributes.items():
- span.set_attribute(key, value)
-
- def process_resource(self, req, resp, resource, params):
- span = req.env.get(_ENVIRON_SPAN_KEY)
- if not span or not span.is_recording():
- return
-
- resource_name = resource.__class__.__name__
- span.set_attribute("falcon.resource", resource_name)
- span.update_name(
- "{0}.on_{1}".format(resource_name, req.method.lower())
- )
-
- def process_response(
- self, req, resp, resource, req_succeeded=None
- ): # pylint:disable=R0201
- span = req.env.get(_ENVIRON_SPAN_KEY)
- if not span or not span.is_recording():
- return
-
- status = resp.status
- reason = None
- if resource is None:
- status = "404"
- reason = "NotFound"
-
- exc_type, exc, _ = sys.exc_info()
- if exc_type and not req_succeeded:
- if "HTTPNotFound" in exc_type.__name__:
- status = "404"
- reason = "NotFound"
- else:
- status = "500"
- reason = "{}: {}".format(exc_type.__name__, exc)
-
- status = status.split(" ")[0]
- try:
- status_code = int(status)
- except ValueError:
- pass
- finally:
- span.set_attribute("http.status_code", status_code)
- span.set_status(
- Status(
- status_code=http_status_to_status_code(status_code),
- description=reason,
- )
- )
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/version.py b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-falcon/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/tests/app.py b/instrumentation/opentelemetry-instrumentation-falcon/tests/app.py
deleted file mode 100644
index dcbfe11b491..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/tests/app.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import falcon
-
-# pylint:disable=R0201,W0613,E0602
-
-
-class HelloWorldResource:
- def _handle_request(self, _, resp):
- # pylint: disable=no-member
- resp.status = falcon.HTTP_201
- resp.body = "Hello World"
-
- def on_get(self, req, resp):
- self._handle_request(req, resp)
-
- def on_put(self, req, resp):
- self._handle_request(req, resp)
-
- def on_patch(self, req, resp):
- self._handle_request(req, resp)
-
- def on_post(self, req, resp):
- self._handle_request(req, resp)
-
- def on_delete(self, req, resp):
- self._handle_request(req, resp)
-
- def on_head(self, req, resp):
- self._handle_request(req, resp)
-
-
-class ErrorResource:
- def on_get(self, req, resp):
- print(non_existent_var) # noqa
-
-
-def make_app():
- app = falcon.API()
- app.add_route("/hello", HelloWorldResource())
- app.add_route("/ping", HelloWorldResource())
- app.add_route("/error", ErrorResource())
- return app
diff --git a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py b/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py
deleted file mode 100644
index fe33a2f2dd1..00000000000
--- a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest.mock import Mock, patch
-
-from falcon import testing
-
-from opentelemetry.instrumentation.falcon import FalconInstrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace.status import StatusCode
-from opentelemetry.util import ExcludeList
-
-from .app import make_app
-
-
-class TestFalconInstrumentation(TestBase):
- def setUp(self):
- super().setUp()
- FalconInstrumentor().instrument()
- self.app = make_app()
-
- def client(self):
- return testing.TestClient(self.app)
-
- def tearDown(self):
- super().tearDown()
- with self.disable_logging():
- FalconInstrumentor().uninstrument()
-
- def test_get(self):
- self._test_method("GET")
-
- def test_post(self):
- self._test_method("POST")
-
- def test_patch(self):
- self._test_method("PATCH")
-
- def test_put(self):
- self._test_method("PUT")
-
- def test_delete(self):
- self._test_method("DELETE")
-
- def test_head(self):
- self._test_method("HEAD")
-
- def _test_method(self, method):
- self.client().simulate_request(method=method, path="/hello")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self.assertEqual(
- span.name, "HelloWorldResource.on_{0}".format(method.lower())
- )
- self.assertEqual(span.status.status_code, StatusCode.UNSET)
- self.assert_span_has_attributes(
- span,
- {
- "component": "http",
- "http.method": method,
- "http.server_name": "falconframework.org",
- "http.scheme": "http",
- "host.port": 80,
- "http.host": "falconframework.org",
- "http.target": "/",
- "net.peer.ip": "127.0.0.1",
- "net.peer.port": "65133",
- "http.flavor": "1.1",
- "falcon.resource": "HelloWorldResource",
- "http.status_text": "Created",
- "http.status_code": 201,
- },
- )
- self.memory_exporter.clear()
-
- def test_404(self):
- self.client().simulate_get("/does-not-exist")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self.assertEqual(span.name, "HTTP GET")
- self.assertEqual(span.status.status_code, StatusCode.ERROR)
- self.assert_span_has_attributes(
- span,
- {
- "component": "http",
- "http.method": "GET",
- "http.server_name": "falconframework.org",
- "http.scheme": "http",
- "host.port": 80,
- "http.host": "falconframework.org",
- "http.target": "/",
- "net.peer.ip": "127.0.0.1",
- "net.peer.port": "65133",
- "http.flavor": "1.1",
- "http.status_text": "Not Found",
- "http.status_code": 404,
- },
- )
-
- def test_500(self):
- try:
- self.client().simulate_get("/error")
- except NameError:
- pass
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self.assertEqual(span.name, "ErrorResource.on_get")
- self.assertFalse(span.status.is_ok)
- self.assertEqual(span.status.status_code, StatusCode.ERROR)
- self.assertEqual(
- span.status.description,
- "NameError: name 'non_existent_var' is not defined",
- )
- self.assert_span_has_attributes(
- span,
- {
- "component": "http",
- "http.method": "GET",
- "http.server_name": "falconframework.org",
- "http.scheme": "http",
- "host.port": 80,
- "http.host": "falconframework.org",
- "http.target": "/",
- "net.peer.ip": "127.0.0.1",
- "net.peer.port": "65133",
- "http.flavor": "1.1",
- "http.status_code": 500,
- },
- )
-
- def test_uninstrument(self):
- self.client().simulate_get(path="/hello")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
-
- self.memory_exporter.clear()
-
- FalconInstrumentor().uninstrument()
- self.app = make_app()
- self.client().simulate_get(path="/hello")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 0)
-
- @patch(
- "opentelemetry.instrumentation.falcon._excluded_urls",
- ExcludeList(["ping"]),
- )
- def test_exclude_lists(self):
- self.client().simulate_get(path="/ping")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 0)
-
- self.client().simulate_get(path="/hello")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- def test_traced_request_attributes(self):
- self.client().simulate_get(path="/hello?q=abc")
- span = self.memory_exporter.get_finished_spans()[0]
- self.assertNotIn("query_string", span.attributes)
- self.memory_exporter.clear()
-
- middleware = self.app._middleware[0][ # pylint:disable=W0212
- 0
- ].__self__
- with patch.object(
- middleware, "_traced_request_attrs", ["query_string"]
- ):
- self.client().simulate_get(path="/hello?q=abc")
- span = self.memory_exporter.get_finished_spans()[0]
- self.assertIn("query_string", span.attributes)
- self.assertEqual(span.attributes["query_string"], "q=abc")
-
- def test_traced_not_recording(self):
- mock_tracer = Mock()
- mock_span = Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = mock_span
- with patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- self.client().simulate_get(path="/hello?q=abc")
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-fastapi/CHANGELOG.md
deleted file mode 100644
index c8c5cea0d3d..00000000000
--- a/instrumentation/opentelemetry-instrumentation-fastapi/CHANGELOG.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.11b0
-
-Released 2020-07-28
-
-- Initial release ([#890](https://github.com/open-telemetry/opentelemetry-python/pull/890))
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/README.rst b/instrumentation/opentelemetry-instrumentation-fastapi/README.rst
deleted file mode 100644
index 4cc612da760..00000000000
--- a/instrumentation/opentelemetry-instrumentation-fastapi/README.rst
+++ /dev/null
@@ -1,43 +0,0 @@
-OpenTelemetry FastAPI Instrumentation
-=======================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-fastapi.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-fastapi/
-
-
-This library provides automatic and manual instrumentation of FastAPI web frameworks,
-instrumenting http requests served by applications utilizing the framework.
-
-auto-instrumentation using the opentelemetry-instrumentation package is also supported.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-fastapi
-
-
-Usage
------
-
-.. code-block:: python
-
- import fastapi
- from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
-
- app = fastapi.FastAPI()
-
- @app.get("/foobar")
- async def foobar():
- return {"message": "hello world"}
-
- FastAPIInstrumentor.instrument_app(app)
-
-
-References
-----------
-
-* `OpenTelemetry Project `_
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg b/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg
deleted file mode 100644
index d6b6bdc54f6..00000000000
--- a/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-fastapi
-description = OpenTelemetry FastAPI Instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-fastapi
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.6
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation-asgi == 0.16.dev0
-
-[options.entry_points]
-opentelemetry_instrumentor =
- fastapi = opentelemetry.instrumentation.fastapi:FastAPIInstrumentor
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
- fastapi ~= 0.58.1
- requests ~= 2.23.0 # needed for testclient
-
-[options.packages.find]
-where = src
diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/setup.py b/instrumentation/opentelemetry-instrumentation-fastapi/setup.py
deleted file mode 100644
index 13c7c5a99c0..00000000000
--- a/instrumentation/opentelemetry-instrumentation-fastapi/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "fastapi",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py
deleted file mode 100644
index 57c9a5bfc79..00000000000
--- a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright The OpenTelemetry 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 typing import Optional
-
-import fastapi
-from starlette.routing import Match
-
-from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
-from opentelemetry.instrumentation.fastapi.version import __version__ # noqa
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-
-
-class FastAPIInstrumentor(BaseInstrumentor):
- """An instrumentor for FastAPI
-
- See `BaseInstrumentor`
- """
-
- _original_fastapi = None
-
- @staticmethod
- def instrument_app(app: fastapi.FastAPI):
- """Instrument an uninstrumented FastAPI application.
- """
- if not getattr(app, "is_instrumented_by_opentelemetry", False):
- app.add_middleware(
- OpenTelemetryMiddleware,
- span_details_callback=_get_route_details,
- )
- app.is_instrumented_by_opentelemetry = True
-
- def _instrument(self, **kwargs):
- self._original_fastapi = fastapi.FastAPI
- fastapi.FastAPI = _InstrumentedFastAPI
-
- def _uninstrument(self, **kwargs):
- fastapi.FastAPI = self._original_fastapi
-
-
-class _InstrumentedFastAPI(fastapi.FastAPI):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.add_middleware(
- OpenTelemetryMiddleware, span_details_callback=_get_route_details
- )
-
-
-def _get_route_details(scope):
- """Callback to retrieve the fastapi route being served.
-
- TODO: there is currently no way to retrieve http.route from
- a starlette application from scope.
-
- See: https://github.com/encode/starlette/pull/804
- """
- app = scope["app"]
- route = None
- for starlette_route in app.routes:
- match, _ = starlette_route.matches(scope)
- if match == Match.FULL:
- route = starlette_route.path
- break
- if match == Match.PARTIAL:
- route = starlette_route.path
- # method only exists for http, if websocket
- # leave it blank.
- span_name = route or scope.get("method", "")
- attributes = {}
- if route:
- attributes["http.route"] = route
- return span_name, attributes
diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/version.py b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py
deleted file mode 100644
index 47617d4e959..00000000000
--- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest
-
-import fastapi
-from fastapi.testclient import TestClient
-
-import opentelemetry.instrumentation.fastapi as otel_fastapi
-from opentelemetry.test.test_base import TestBase
-
-
-class TestFastAPIManualInstrumentation(TestBase):
- def _create_app(self):
- app = self._create_fastapi_app()
- self._instrumentor.instrument_app(app)
- return app
-
- def setUp(self):
- super().setUp()
- self._instrumentor = otel_fastapi.FastAPIInstrumentor()
- self._app = self._create_app()
- self._client = TestClient(self._app)
-
- def test_basic_fastapi_call(self):
- self._client.get("/foobar")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 3)
- for span in spans:
- self.assertIn("/foobar", span.name)
-
- def test_fastapi_route_attribute_added(self):
- """Ensure that fastapi routes are used as the span name."""
- self._client.get("/user/123")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 3)
- for span in spans:
- self.assertIn("/user/{username}", span.name)
- self.assertEqual(
- spans[-1].attributes["http.route"], "/user/{username}"
- )
- # ensure that at least one attribute that is populated by
- # the asgi instrumentation is successfully feeding though.
- self.assertEqual(spans[-1].attributes["http.flavor"], "1.1")
-
- @staticmethod
- def _create_fastapi_app():
- app = fastapi.FastAPI()
-
- @app.get("/foobar")
- async def _():
- return {"message": "hello world"}
-
- @app.get("/user/{username}")
- async def _(username: str):
- return {"message": username}
-
- return app
-
-
-class TestAutoInstrumentation(TestFastAPIManualInstrumentation):
- """Test the auto-instrumented variant
-
- Extending the manual instrumentation as most test cases apply
- to both.
- """
-
- def _create_app(self):
- # instrumentation is handled by the instrument call
- self._instrumentor.instrument()
- return self._create_fastapi_app()
-
- def tearDown(self):
- self._instrumentor.uninstrument()
- super().tearDown()
-
-
-class TestAutoInstrumentationLogic(unittest.TestCase):
- def test_instrumentation(self):
- """Verify that instrumentation methods are instrumenting and
- removing as expected.
- """
- instrumentor = otel_fastapi.FastAPIInstrumentor()
- original = fastapi.FastAPI
- instrumentor.instrument()
- try:
- instrumented = fastapi.FastAPI
- self.assertIsNot(original, instrumented)
- finally:
- instrumentor.uninstrument()
-
- should_be_original = fastapi.FastAPI
- self.assertIs(original, should_be_original)
diff --git a/instrumentation/opentelemetry-instrumentation-flask/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-flask/CHANGELOG.md
deleted file mode 100644
index 4c7e7a055b8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/CHANGELOG.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.15b0
-
-Released 2020-11-02
-
-- Use `url.rule` instead of `request.endpoint` for span name
- ([#1260](https://github.com/open-telemetry/opentelemetry-python/pull/1260))
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-flask
- ([#961](https://github.com/open-telemetry/opentelemetry-python/pull/961))
-- Update environment variable names, prefix changed from `OPENTELEMETRY` to `OTEL` ([#904](https://github.com/open-telemetry/opentelemetry-python/pull/904))
-
-## Version 0.11b0
-
-- Use one general exclude list instead of two ([#872](https://github.com/open-telemetry/opentelemetry-python/pull/872))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Add exclude list for paths and hosts
- ([#630](https://github.com/open-telemetry/opentelemetry-python/pull/630))
-
-## 0.6b0
-
-Released 2020-03-30
-
-- Add an entry_point to be usable in auto-instrumentation
- ([#327](https://github.com/open-telemetry/opentelemetry-python/pull/327))
-
-## 0.4a0
-
-Released 2020-02-21
-
-- Use string keys for WSGI environ values
- ([#366](https://github.com/open-telemetry/opentelemetry-python/pull/366))
-
-## 0.3a0
-
-Released 2019-12-11
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-flask/LICENSE b/instrumentation/opentelemetry-instrumentation-flask/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-flask/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-flask/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-flask/README.rst b/instrumentation/opentelemetry-instrumentation-flask/README.rst
deleted file mode 100644
index f79d8fd6041..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/README.rst
+++ /dev/null
@@ -1,38 +0,0 @@
-OpenTelemetry Flask Tracing
-===========================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-flask.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-flask/
-
-This library builds on the OpenTelemetry WSGI middleware to track web requests
-in Flask applications.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-flask
-
-Configuration
--------------
-
-Exclude lists
-*************
-To exclude certain URLs from being tracked, set the environment variable ``OTEL_PYTHON_FLASK_EXCLUDED_URLS`` with comma delimited regexes representing which URLs to exclude.
-
-For example,
-
-::
-
- export OTEL_PYTHON_FLASK_EXCLUDED_URLS="client/.*/info,healthcheck"
-
-will exclude requests such as ``https://site/client/123/info`` and ``https://site/xyz/healthcheck``.
-
-References
-----------
-
-* `OpenTelemetry Flask Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-flask/setup.cfg b/instrumentation/opentelemetry-instrumentation-flask/setup.cfg
deleted file mode 100644
index 2e9f943ceb1..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/setup.cfg
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-flask
-description = Flask instrumentation for OpenTelemetry
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-flask
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- flask ~= 1.0
- opentelemetry-instrumentation-wsgi == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- opentelemetry-api == 0.16.dev0
-
-[options.extras_require]
-test =
- flask~=1.0
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
diff --git a/instrumentation/opentelemetry-instrumentation-flask/setup.py b/instrumentation/opentelemetry-instrumentation-flask/setup.py
deleted file mode 100644
index 587b697a7b0..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/setup.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "flask", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(
- version=PACKAGE_INFO["__version__"],
- entry_points={
- "opentelemetry_instrumentor": [
- "flask = opentelemetry.instrumentation.flask:FlaskInstrumentor"
- ]
- },
-)
diff --git a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py
deleted file mode 100644
index 1235b09a307..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py
+++ /dev/null
@@ -1,227 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# Note: This package is not named "flask" because of
-# https://github.com/PyCQA/pylint/issues/2648
-
-"""
-This library builds on the OpenTelemetry WSGI middleware to track web requests
-in Flask applications. In addition to opentelemetry-instrumentation-wsgi, it supports
-flask-specific features such as:
-
-* The Flask endpoint name is used as the Span name.
-* The ``http.route`` Span attribute is set so that one can see which URL rule
- matched a request.
-
-Usage
------
-
-.. code-block:: python
-
- from flask import Flask
- from opentelemetry.instrumentation.flask import FlaskInstrumentor
-
- app = Flask(__name__)
-
- FlaskInstrumentor().instrument_app(app)
-
- @app.route("/")
- def hello():
- return "Hello!"
-
- if __name__ == "__main__":
- app.run(debug=True)
-
-API
----
-"""
-
-from logging import getLogger
-
-import flask
-
-import opentelemetry.instrumentation.wsgi as otel_wsgi
-from opentelemetry import configuration, context, propagators, trace
-from opentelemetry.instrumentation.flask.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.util import ExcludeList, time_ns
-
-_logger = getLogger(__name__)
-
-_ENVIRON_STARTTIME_KEY = "opentelemetry-flask.starttime_key"
-_ENVIRON_SPAN_KEY = "opentelemetry-flask.span_key"
-_ENVIRON_ACTIVATION_KEY = "opentelemetry-flask.activation_key"
-_ENVIRON_TOKEN = "opentelemetry-flask.token"
-
-
-def get_excluded_urls():
- urls = configuration.Configuration().FLASK_EXCLUDED_URLS or []
- if urls:
- urls = str.split(urls, ",")
- return ExcludeList(urls)
-
-
-_excluded_urls = get_excluded_urls()
-
-
-def _rewrapped_app(wsgi_app):
- def _wrapped_app(environ, start_response):
- # We want to measure the time for route matching, etc.
- # In theory, we could start the span here and use
- # update_name later but that API is "highly discouraged" so
- # we better avoid it.
- environ[_ENVIRON_STARTTIME_KEY] = time_ns()
-
- def _start_response(status, response_headers, *args, **kwargs):
- if not _excluded_urls.url_disabled(flask.request.url):
- span = flask.request.environ.get(_ENVIRON_SPAN_KEY)
-
- if span:
- otel_wsgi.add_response_attributes(
- span, status, response_headers
- )
- else:
- _logger.warning(
- "Flask environ's OpenTelemetry span "
- "missing at _start_response(%s)",
- status,
- )
-
- return start_response(status, response_headers, *args, **kwargs)
-
- return wsgi_app(environ, _start_response)
-
- return _wrapped_app
-
-
-def _before_request():
- if _excluded_urls.url_disabled(flask.request.url):
- return
-
- environ = flask.request.environ
- span_name = None
- try:
- span_name = flask.request.url_rule.rule
- except AttributeError:
- pass
- if span_name is None:
- span_name = otel_wsgi.get_default_span_name(environ)
- token = context.attach(
- propagators.extract(otel_wsgi.carrier_getter, environ)
- )
-
- tracer = trace.get_tracer(__name__, __version__)
-
- span = tracer.start_span(
- span_name,
- kind=trace.SpanKind.SERVER,
- start_time=environ.get(_ENVIRON_STARTTIME_KEY),
- )
- if span.is_recording():
- attributes = otel_wsgi.collect_request_attributes(environ)
- if flask.request.url_rule:
- # For 404 that result from no route found, etc, we
- # don't have a url_rule.
- attributes["http.route"] = flask.request.url_rule.rule
- for key, value in attributes.items():
- span.set_attribute(key, value)
-
- activation = tracer.use_span(span, end_on_exit=True)
- activation.__enter__()
- environ[_ENVIRON_ACTIVATION_KEY] = activation
- environ[_ENVIRON_SPAN_KEY] = span
- environ[_ENVIRON_TOKEN] = token
-
-
-def _teardown_request(exc):
- if _excluded_urls.url_disabled(flask.request.url):
- return
-
- activation = flask.request.environ.get(_ENVIRON_ACTIVATION_KEY)
- if not activation:
- _logger.warning(
- "Flask environ's OpenTelemetry activation missing"
- "at _teardown_flask_request(%s)",
- exc,
- )
- return
-
- if exc is None:
- activation.__exit__(None, None, None)
- else:
- activation.__exit__(
- type(exc), exc, getattr(exc, "__traceback__", None)
- )
- context.detach(flask.request.environ.get(_ENVIRON_TOKEN))
-
-
-class _InstrumentedFlask(flask.Flask):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- self._original_wsgi_ = self.wsgi_app
- self.wsgi_app = _rewrapped_app(self.wsgi_app)
-
- self.before_request(_before_request)
- self.teardown_request(_teardown_request)
-
-
-class FlaskInstrumentor(BaseInstrumentor):
- # pylint: disable=protected-access,attribute-defined-outside-init
- """An instrumentor for flask.Flask
-
- See `BaseInstrumentor`
- """
-
- def _instrument(self, **kwargs):
- self._original_flask = flask.Flask
- flask.Flask = _InstrumentedFlask
-
- def instrument_app(self, app): # pylint: disable=no-self-use
- if not hasattr(app, "_is_instrumented"):
- app._is_instrumented = False
-
- if not app._is_instrumented:
- app._original_wsgi_app = app.wsgi_app
- app.wsgi_app = _rewrapped_app(app.wsgi_app)
-
- app.before_request(_before_request)
- app.teardown_request(_teardown_request)
- app._is_instrumented = True
- else:
- _logger.warning(
- "Attempting to instrument Flask app while already instrumented"
- )
-
- def _uninstrument(self, **kwargs):
- flask.Flask = self._original_flask
-
- def uninstrument_app(self, app): # pylint: disable=no-self-use
- if not hasattr(app, "_is_instrumented"):
- app._is_instrumented = False
-
- if app._is_instrumented:
- app.wsgi_app = app._original_wsgi_app
-
- # FIXME add support for other Flask blueprints that are not None
- app.before_request_funcs[None].remove(_before_request)
- app.teardown_request_funcs[None].remove(_teardown_request)
- del app._original_wsgi_app
-
- app._is_instrumented = False
- else:
- _logger.warning(
- "Attempting to uninstrument Flask "
- "app while already uninstrumented"
- )
diff --git a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/version.py b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-flask/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/base_test.py b/instrumentation/opentelemetry-instrumentation-flask/tests/base_test.py
deleted file mode 100644
index c2bc646e1ba..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/tests/base_test.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright The OpenTelemetry 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 werkzeug.test import Client
-from werkzeug.wrappers import BaseResponse
-
-from opentelemetry.configuration import Configuration
-
-
-class InstrumentationTest:
- def setUp(self): # pylint: disable=invalid-name
- super().setUp() # pylint: disable=no-member
- Configuration._reset() # pylint: disable=protected-access
-
- @staticmethod
- def _hello_endpoint(helloid):
- if helloid == 500:
- raise ValueError(":-(")
- return "Hello: " + str(helloid)
-
- def _common_initialization(self):
- def excluded_endpoint():
- return "excluded"
-
- def excluded2_endpoint():
- return "excluded2"
-
- # pylint: disable=no-member
- self.app.route("/hello/")(self._hello_endpoint)
- self.app.route("/excluded/")(self._hello_endpoint)
- self.app.route("/excluded")(excluded_endpoint)
- self.app.route("/excluded2")(excluded2_endpoint)
-
- # pylint: disable=attribute-defined-outside-init
- self.client = Client(self.app, BaseResponse)
diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_automatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_automatic.py
deleted file mode 100644
index d081bed9ee8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_automatic.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright The OpenTelemetry 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 flask
-from werkzeug.test import Client
-from werkzeug.wrappers import BaseResponse
-
-from opentelemetry.instrumentation.flask import FlaskInstrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.test.wsgitestutil import WsgiTestBase
-
-# pylint: disable=import-error
-from .base_test import InstrumentationTest
-
-
-class TestAutomatic(InstrumentationTest, TestBase, WsgiTestBase):
- def setUp(self):
- super().setUp()
-
- FlaskInstrumentor().instrument()
-
- self.app = flask.Flask(__name__)
-
- self._common_initialization()
-
- def tearDown(self):
- super().tearDown()
- with self.disable_logging():
- FlaskInstrumentor().uninstrument()
-
- def test_uninstrument(self):
- # pylint: disable=access-member-before-definition
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- FlaskInstrumentor().uninstrument()
- self.app = flask.Flask(__name__)
-
- self.app.route("/hello/")(self._hello_endpoint)
- # pylint: disable=attribute-defined-outside-init
- self.client = Client(self.app, BaseResponse)
-
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py
deleted file mode 100644
index a907890523c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest.mock import Mock, patch
-
-from flask import Flask, request
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.flask import FlaskInstrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.test.wsgitestutil import WsgiTestBase
-from opentelemetry.util import ExcludeList
-
-# pylint: disable=import-error
-from .base_test import InstrumentationTest
-
-
-def expected_attributes(override_attributes):
- default_attributes = {
- "component": "http",
- "http.method": "GET",
- "http.server_name": "localhost",
- "http.scheme": "http",
- "host.port": 80,
- "http.host": "localhost",
- "http.target": "/",
- "http.flavor": "1.1",
- "http.status_text": "OK",
- "http.status_code": 200,
- }
- for key, val in override_attributes.items():
- default_attributes[key] = val
- return default_attributes
-
-
-class TestProgrammatic(InstrumentationTest, TestBase, WsgiTestBase):
- def setUp(self):
- super().setUp()
-
- self.app = Flask(__name__)
-
- FlaskInstrumentor().instrument_app(self.app)
-
- self._common_initialization()
-
- def tearDown(self):
- super().tearDown()
- with self.disable_logging():
- FlaskInstrumentor().uninstrument_app(self.app)
-
- def test_uninstrument(self):
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- FlaskInstrumentor().uninstrument_app(self.app)
-
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- # pylint: disable=no-member
- def test_only_strings_in_environ(self):
- """
- Some WSGI servers (such as Gunicorn) expect keys in the environ object
- to be strings
-
- OpenTelemetry should adhere to this convention.
- """
- nonstring_keys = set()
-
- def assert_environ():
- for key in request.environ:
- if not isinstance(key, str):
- nonstring_keys.add(key)
- return "hi"
-
- self.app.route("/assert_environ")(assert_environ)
- self.client.get("/assert_environ")
- self.assertEqual(nonstring_keys, set())
-
- def test_simple(self):
- expected_attrs = expected_attributes(
- {"http.target": "/hello/123", "http.route": "/hello/"}
- )
- self.client.get("/hello/123")
-
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
- self.assertEqual(span_list[0].name, "/hello/")
- self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
- self.assertEqual(span_list[0].attributes, expected_attrs)
-
- def test_not_recording(self):
- mock_tracer = Mock()
- mock_span = Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = mock_span
- with patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- self.client.get("/hello/123")
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_404(self):
- expected_attrs = expected_attributes(
- {
- "http.method": "POST",
- "http.target": "/bye",
- "http.status_text": "NOT FOUND",
- "http.status_code": 404,
- }
- )
-
- resp = self.client.post("/bye")
- self.assertEqual(404, resp.status_code)
- resp.close()
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
- self.assertEqual(span_list[0].name, "HTTP POST")
- self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
- self.assertEqual(span_list[0].attributes, expected_attrs)
-
- def test_internal_error(self):
- expected_attrs = expected_attributes(
- {
- "http.target": "/hello/500",
- "http.route": "/hello/",
- "http.status_text": "INTERNAL SERVER ERROR",
- "http.status_code": 500,
- }
- )
- resp = self.client.get("/hello/500")
- self.assertEqual(500, resp.status_code)
- resp.close()
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
- self.assertEqual(span_list[0].name, "/hello/")
- self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
- self.assertEqual(span_list[0].attributes, expected_attrs)
-
- @patch(
- "opentelemetry.instrumentation.flask._excluded_urls",
- ExcludeList(["http://localhost/excluded_arg/123", "excluded_noarg"]),
- )
- def test_exclude_lists(self):
- self.client.get("/excluded_arg/123")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 0)
-
- self.client.get("/excluded_arg/125")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- self.client.get("/excluded_noarg")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- self.client.get("/excluded_noarg2")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-grpc/CHANGELOG.md
deleted file mode 100644
index ed6889dcb75..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/CHANGELOG.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-grpc
- ([#969](https://github.com/open-telemetry/opentelemetry-python/pull/969))
-
-## Version 0.11b0
-
-Released 2020-07-28
-
-- Add status code to gRPC client spans
- ([896](https://github.com/open-telemetry/opentelemetry-python/pull/896))
-- Add gRPC client and server instrumentors
- ([788](https://github.com/open-telemetry/opentelemetry-python/pull/788))
-
-- Add metric recording (bytes in/out, errors, latency) to gRPC client
-
-## 0.8b0
-
-Released 2020-05-27
-
-- lint: version of grpc causes lint issues
- ([#696](https://github.com/open-telemetry/opentelemetry-python/pull/696))
-
-## 0.6b0
-
-Released 2020-03-30
-
-- Add gRPC integration
- ([#476](https://github.com/open-telemetry/opentelemetry-python/pull/476))
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/LICENSE b/instrumentation/opentelemetry-instrumentation-grpc/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-grpc/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-grpc/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/README.rst b/instrumentation/opentelemetry-instrumentation-grpc/README.rst
deleted file mode 100644
index 176bdf1a39b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/README.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-OpenTelemetry gRPC Integration
-==============================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-grpc.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-grpc/
-
-Client and server interceptors for `gRPC Python`_.
-
-.. _gRPC Python: https://grpc.github.io/grpc/python/grpc.html
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-grpc
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/setup.cfg b/instrumentation/opentelemetry-instrumentation-grpc/setup.cfg
deleted file mode 100644
index da31572e02c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/setup.cfg
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-[metadata]
-name = opentelemetry-instrumentation-grpc
-description = OpenTelemetry gRPC instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-grpc
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-sdk == 0.16.dev0
- grpcio ~= 1.27
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
- opentelemetry-sdk == 0.16.dev0
- protobuf == 3.12.2
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- grpc_client = opentelemetry.instrumentation.grpc:GrpcInstrumentorClient
- grpc_server = opentelemetry.instrumentation.grpc:GrpcInstrumentorServer
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/setup.py b/instrumentation/opentelemetry-instrumentation-grpc/setup.py
deleted file mode 100644
index 87c720aea23..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/setup.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "grpc", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py
deleted file mode 100644
index 776e29e8e20..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py
+++ /dev/null
@@ -1,248 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# pylint:disable=no-name-in-module
-# pylint:disable=relative-beyond-top-level
-# pylint:disable=import-error
-# pylint:disable=no-self-use
-"""
-Usage Client
-------------
-.. code-block:: python
-
- import logging
-
- import grpc
-
- from opentelemetry import trace
- from opentelemetry.instrumentation.grpc import GrpcInstrumentorClient, client_interceptor
- from opentelemetry.sdk.trace import TracerProvider
- from opentelemetry.sdk.trace.export import (
- ConsoleSpanExporter,
- SimpleExportSpanProcessor,
- )
-
- from opentelemetry import metrics
- from opentelemetry.sdk.metrics import MeterProvider
- from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter
-
- try:
- from .gen import helloworld_pb2, helloworld_pb2_grpc
- except ImportError:
- from gen import helloworld_pb2, helloworld_pb2_grpc
-
- trace.set_tracer_provider(TracerProvider())
- trace.get_tracer_provider().add_span_processor(
- SimpleExportSpanProcessor(ConsoleSpanExporter())
- )
-
- # Set meter provider to opentelemetry-sdk's MeterProvider
- metrics.set_meter_provider(MeterProvider())
-
- # Optional - export GRPC specific metrics (latency, bytes in/out, errors) by passing an exporter
- instrumentor = GrpcInstrumentorClient(exporter=ConsoleMetricsExporter(), interval=10)
- instrumentor.instrument()
-
- def run():
- with grpc.insecure_channel("localhost:50051") as channel:
-
- stub = helloworld_pb2_grpc.GreeterStub(channel)
- response = stub.SayHello(helloworld_pb2.HelloRequest(name="YOU"))
-
- print("Greeter client received: " + response.message)
-
-
- if __name__ == "__main__":
- logging.basicConfig()
- run()
-
-Usage Server
-------------
-.. code-block:: python
-
- import logging
- from concurrent import futures
-
- import grpc
-
- from opentelemetry import trace
- from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer
- from opentelemetry.sdk.trace import TracerProvider
- from opentelemetry.sdk.trace.export import (
- ConsoleSpanExporter,
- SimpleExportSpanProcessor,
- )
-
- try:
- from .gen import helloworld_pb2, helloworld_pb2_grpc
- except ImportError:
- from gen import helloworld_pb2, helloworld_pb2_grpc
-
- trace.set_tracer_provider(TracerProvider())
- trace.get_tracer_provider().add_span_processor(
- SimpleExportSpanProcessor(ConsoleSpanExporter())
- )
-
- grpc_server_instrumentor = GrpcInstrumentorServer()
- grpc_server_instrumentor.instrument()
-
- class Greeter(helloworld_pb2_grpc.GreeterServicer):
- def SayHello(self, request, context):
- return helloworld_pb2.HelloReply(message="Hello, %s!" % request.name)
-
-
- def serve():
-
- server = grpc.server(futures.ThreadPoolExecutor())
-
- helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
- server.add_insecure_port("[::]:50051")
- server.start()
- server.wait_for_termination()
-
-
- if __name__ == "__main__":
- logging.basicConfig()
- serve()
-
-You can also add the instrumentor manually, rather than using
-:py:class:`~opentelemetry.instrumentation.grpc.GrpcInstrumentorServer`:
-
-.. code-block:: python
-
- from opentelemetry.instrumentation.grpc import server_interceptor
-
- server = grpc.server(futures.ThreadPoolExecutor(),
- interceptors = [server_interceptor()])
-
-"""
-from functools import partial
-
-import grpc
-from wrapt import wrap_function_wrapper as _wrap
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.grpc.grpcext import intercept_channel
-from opentelemetry.instrumentation.grpc.version import __version__
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.utils import unwrap
-
-# pylint:disable=import-outside-toplevel
-# pylint:disable=import-self
-# pylint:disable=unused-argument
-# isort:skip
-
-
-class GrpcInstrumentorServer(BaseInstrumentor):
- """
- Globally instrument the grpc server.
-
- Usage::
-
- grpc_server_instrumentor = GrpcInstrumentorServer()
- grpc_server_instrumentor.instrument()
-
- """
-
- # pylint:disable=attribute-defined-outside-init
-
- def _instrument(self, **kwargs):
- self._original_func = grpc.server
-
- def server(*args, **kwargs):
- if "interceptors" in kwargs:
- # add our interceptor as the first
- kwargs["interceptors"].insert(0, server_interceptor())
- else:
- kwargs["interceptors"] = [server_interceptor()]
- return self._original_func(*args, **kwargs)
-
- grpc.server = server
-
- def _uninstrument(self, **kwargs):
- grpc.server = self._original_func
-
-
-class GrpcInstrumentorClient(BaseInstrumentor):
- def _instrument(self, **kwargs):
- exporter = kwargs.get("exporter", None)
- interval = kwargs.get("interval", 30)
- if kwargs.get("channel_type") == "secure":
- _wrap(
- "grpc",
- "secure_channel",
- partial(self.wrapper_fn, exporter, interval),
- )
-
- else:
- _wrap(
- "grpc",
- "insecure_channel",
- partial(self.wrapper_fn, exporter, interval),
- )
-
- def _uninstrument(self, **kwargs):
- if kwargs.get("channel_type") == "secure":
- unwrap(grpc, "secure_channel")
-
- else:
- unwrap(grpc, "insecure_channel")
-
- def wrapper_fn(
- self, exporter, interval, original_func, instance, args, kwargs
- ):
- channel = original_func(*args, **kwargs)
- tracer_provider = kwargs.get("tracer_provider")
- return intercept_channel(
- channel,
- client_interceptor(
- tracer_provider=tracer_provider,
- exporter=exporter,
- interval=interval,
- ),
- )
-
-
-def client_interceptor(tracer_provider=None, exporter=None, interval=30):
- """Create a gRPC client channel interceptor.
-
- Args:
- tracer: The tracer to use to create client-side spans.
- exporter: The exporter that will receive client metrics
- interval: Time between every export call
-
- Returns:
- An invocation-side interceptor object.
- """
- from . import _client
-
- tracer = trace.get_tracer(__name__, __version__, tracer_provider)
-
- return _client.OpenTelemetryClientInterceptor(tracer, exporter, interval)
-
-
-def server_interceptor(tracer_provider=None):
- """Create a gRPC server interceptor.
-
- Args:
- tracer: The tracer to use to create server-side spans.
-
- Returns:
- A service-side interceptor object.
- """
- from . import _server
-
- tracer = trace.get_tracer(__name__, __version__, tracer_provider)
-
- return _server.OpenTelemetryServerInterceptor(tracer)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py
deleted file mode 100644
index f8a72931f90..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py
+++ /dev/null
@@ -1,273 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# pylint:disable=relative-beyond-top-level
-# pylint:disable=arguments-differ
-# pylint:disable=no-member
-# pylint:disable=signature-differs
-
-"""Implementation of the invocation-side open-telemetry interceptor."""
-
-from collections import OrderedDict
-from typing import MutableMapping
-
-import grpc
-
-from opentelemetry import metrics, propagators, trace
-from opentelemetry.sdk.metrics.export.controller import PushController
-from opentelemetry.trace.status import Status, StatusCode
-
-from . import grpcext
-from ._utilities import RpcInfo, TimedMetricRecorder
-
-
-class _GuardedSpan:
- def __init__(self, span):
- self.span = span
- self.generated_span = None
- self._engaged = True
-
- def __enter__(self):
- self.generated_span = self.span.__enter__()
- return self
-
- def __exit__(self, *args, **kwargs):
- if self._engaged:
- self.generated_span = None
- return self.span.__exit__(*args, **kwargs)
- return False
-
- def release(self):
- self._engaged = False
- return self.span
-
-
-def _inject_span_context(metadata: MutableMapping[str, str]) -> None:
- # pylint:disable=unused-argument
- def append_metadata(
- carrier: MutableMapping[str, str], key: str, value: str
- ):
- metadata[key] = value
-
- # Inject current active span from the context
- propagators.inject(append_metadata, metadata)
-
-
-def _make_future_done_callback(span, rpc_info, client_info, metrics_recorder):
- def callback(response_future):
- with span:
- code = response_future.code()
- if code != grpc.StatusCode.OK:
- rpc_info.error = code
- return
- response = response_future.result()
- rpc_info.response = response
- if "ByteSize" in dir(response):
- metrics_recorder.record_bytes_in(
- response.ByteSize(), client_info.full_method
- )
-
- return callback
-
-
-class OpenTelemetryClientInterceptor(
- grpcext.UnaryClientInterceptor, grpcext.StreamClientInterceptor
-):
- def __init__(self, tracer, exporter, interval):
- self._tracer = tracer
-
- self._meter = None
- if exporter and interval:
- self._meter = metrics.get_meter(__name__)
- self.controller = PushController(
- meter=self._meter, exporter=exporter, interval=interval
- )
- self._metrics_recorder = TimedMetricRecorder(self._meter, "client")
-
- def _start_span(self, method):
- return self._tracer.start_as_current_span(
- name=method, kind=trace.SpanKind.CLIENT
- )
-
- # pylint:disable=no-self-use
- def _trace_result(self, guarded_span, rpc_info, result, client_info):
- # If the RPC is called asynchronously, release the guard and add a
- # callback so that the span can be finished once the future is done.
- if isinstance(result, grpc.Future):
- result.add_done_callback(
- _make_future_done_callback(
- guarded_span.release(),
- rpc_info,
- client_info,
- self._metrics_recorder,
- )
- )
- return result
- response = result
- # Handle the case when the RPC is initiated via the with_call
- # method and the result is a tuple with the first element as the
- # response.
- # http://www.grpc.io/grpc/python/grpc.html#grpc.UnaryUnaryMultiCallable.with_call
- if isinstance(result, tuple):
- response = result[0]
- rpc_info.response = response
-
- if "ByteSize" in dir(response):
- self._metrics_recorder.record_bytes_in(
- response.ByteSize(), client_info.full_method
- )
- return result
-
- def _start_guarded_span(self, *args, **kwargs):
- return _GuardedSpan(self._start_span(*args, **kwargs))
-
- def _bytes_out_iterator_wrapper(self, iterator, client_info):
- for request in iterator:
- if "ByteSize" in dir(request):
- self._metrics_recorder.record_bytes_out(
- request.ByteSize(), client_info.full_method
- )
- yield request
-
- def intercept_unary(self, request, metadata, client_info, invoker):
- if not metadata:
- mutable_metadata = OrderedDict()
- else:
- mutable_metadata = OrderedDict(metadata)
-
- with self._start_guarded_span(client_info.full_method) as guarded_span:
- with self._metrics_recorder.record_latency(
- client_info.full_method
- ):
- _inject_span_context(mutable_metadata)
- metadata = tuple(mutable_metadata.items())
-
- # If protobuf is used, we can record the bytes in/out. Otherwise, we have no way
- # to get the size of the request/response properly, so don't record anything
- if "ByteSize" in dir(request):
- self._metrics_recorder.record_bytes_out(
- request.ByteSize(), client_info.full_method
- )
-
- rpc_info = RpcInfo(
- full_method=client_info.full_method,
- metadata=metadata,
- timeout=client_info.timeout,
- request=request,
- )
-
- try:
- result = invoker(request, metadata)
- except grpc.RpcError:
- guarded_span.generated_span.set_status(
- Status(StatusCode.ERROR)
- )
- raise
-
- return self._trace_result(
- guarded_span, rpc_info, result, client_info
- )
-
- # For RPCs that stream responses, the result can be a generator. To record
- # the span across the generated responses and detect any errors, we wrap
- # the result in a new generator that yields the response values.
- def _intercept_server_stream(
- self, request_or_iterator, metadata, client_info, invoker
- ):
- if not metadata:
- mutable_metadata = OrderedDict()
- else:
- mutable_metadata = OrderedDict(metadata)
-
- with self._start_span(client_info.full_method) as span:
- with self._metrics_recorder.record_latency(
- client_info.full_method
- ):
- _inject_span_context(mutable_metadata)
- metadata = tuple(mutable_metadata.items())
- rpc_info = RpcInfo(
- full_method=client_info.full_method,
- metadata=metadata,
- timeout=client_info.timeout,
- )
-
- if client_info.is_client_stream:
- rpc_info.request = request_or_iterator
- request_or_iterator = self._bytes_out_iterator_wrapper(
- request_or_iterator, client_info
- )
- else:
- if "ByteSize" in dir(request_or_iterator):
- self._metrics_recorder.record_bytes_out(
- request_or_iterator.ByteSize(),
- client_info.full_method,
- )
-
- try:
- result = invoker(request_or_iterator, metadata)
-
- # Rewrap the result stream into a generator, and record the bytes received
- for response in result:
- if "ByteSize" in dir(response):
- self._metrics_recorder.record_bytes_in(
- response.ByteSize(), client_info.full_method
- )
- yield response
- except grpc.RpcError:
- span.set_status(Status(StatusCode.ERROR))
- raise
-
- def intercept_stream(
- self, request_or_iterator, metadata, client_info, invoker
- ):
- if client_info.is_server_stream:
- return self._intercept_server_stream(
- request_or_iterator, metadata, client_info, invoker
- )
-
- if not metadata:
- mutable_metadata = OrderedDict()
- else:
- mutable_metadata = OrderedDict(metadata)
-
- with self._start_guarded_span(client_info.full_method) as guarded_span:
- with self._metrics_recorder.record_latency(
- client_info.full_method
- ):
- _inject_span_context(mutable_metadata)
- metadata = tuple(mutable_metadata.items())
- rpc_info = RpcInfo(
- full_method=client_info.full_method,
- metadata=metadata,
- timeout=client_info.timeout,
- request=request_or_iterator,
- )
-
- rpc_info.request = request_or_iterator
-
- request_or_iterator = self._bytes_out_iterator_wrapper(
- request_or_iterator, client_info
- )
-
- try:
- result = invoker(request_or_iterator, metadata)
- except grpc.RpcError:
- guarded_span.generated_span.set_status(
- Status(StatusCode.ERROR)
- )
- raise
-
- return self._trace_result(
- guarded_span, rpc_info, result, client_info
- )
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py
deleted file mode 100644
index 087cf4f9ccb..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py
+++ /dev/null
@@ -1,246 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# pylint:disable=relative-beyond-top-level
-# pylint:disable=arguments-differ
-# pylint:disable=no-member
-# pylint:disable=signature-differs
-
-"""
-Implementation of the service-side open-telemetry interceptor.
-"""
-
-import logging
-from contextlib import contextmanager
-
-import grpc
-
-from opentelemetry import propagators, trace
-from opentelemetry.context import attach, detach
-from opentelemetry.trace.propagation.textmap import DictGetter
-from opentelemetry.trace.status import Status, StatusCode
-
-logger = logging.getLogger(__name__)
-
-
-# wrap an RPC call
-# see https://github.com/grpc/grpc/issues/18191
-def _wrap_rpc_behavior(handler, continuation):
- if handler is None:
- return None
-
- if handler.request_streaming and handler.response_streaming:
- behavior_fn = handler.stream_stream
- handler_factory = grpc.stream_stream_rpc_method_handler
- elif handler.request_streaming and not handler.response_streaming:
- behavior_fn = handler.stream_unary
- handler_factory = grpc.stream_unary_rpc_method_handler
- elif not handler.request_streaming and handler.response_streaming:
- behavior_fn = handler.unary_stream
- handler_factory = grpc.unary_stream_rpc_method_handler
- else:
- behavior_fn = handler.unary_unary
- handler_factory = grpc.unary_unary_rpc_method_handler
-
- return handler_factory(
- continuation(
- behavior_fn, handler.request_streaming, handler.response_streaming
- ),
- request_deserializer=handler.request_deserializer,
- response_serializer=handler.response_serializer,
- )
-
-
-# pylint:disable=abstract-method
-class _OpenTelemetryServicerContext(grpc.ServicerContext):
- def __init__(self, servicer_context, active_span):
- self._servicer_context = servicer_context
- self._active_span = active_span
- self.code = grpc.StatusCode.OK
- self.details = None
- super().__init__()
-
- def is_active(self, *args, **kwargs):
- return self._servicer_context.is_active(*args, **kwargs)
-
- def time_remaining(self, *args, **kwargs):
- return self._servicer_context.time_remaining(*args, **kwargs)
-
- def cancel(self, *args, **kwargs):
- return self._servicer_context.cancel(*args, **kwargs)
-
- def add_callback(self, *args, **kwargs):
- return self._servicer_context.add_callback(*args, **kwargs)
-
- def disable_next_message_compression(self):
- return self._service_context.disable_next_message_compression()
-
- def invocation_metadata(self, *args, **kwargs):
- return self._servicer_context.invocation_metadata(*args, **kwargs)
-
- def peer(self):
- return self._servicer_context.peer()
-
- def peer_identities(self):
- return self._servicer_context.peer_identities()
-
- def peer_identity_key(self):
- return self._servicer_context.peer_identity_key()
-
- def auth_context(self):
- return self._servicer_context.auth_context()
-
- def set_compression(self, compression):
- return self._servicer_context.set_compression(compression)
-
- def send_initial_metadata(self, *args, **kwargs):
- return self._servicer_context.send_initial_metadata(*args, **kwargs)
-
- def set_trailing_metadata(self, *args, **kwargs):
- return self._servicer_context.set_trailing_metadata(*args, **kwargs)
-
- def abort(self, code, details):
- self.code = code
- self.details = details
- self._active_span.set_attribute("rpc.grpc.status_code", code.name)
- self._active_span.set_status(
- Status(status_code=StatusCode.ERROR, description=details)
- )
- return self._servicer_context.abort(code, details)
-
- def abort_with_status(self, status):
- return self._servicer_context.abort_with_status(status)
-
- def set_code(self, code):
- self.code = code
- # use details if we already have it, otherwise the status description
- details = self.details or code.value[1]
- self._active_span.set_attribute("rpc.grpc.status_code", code.name)
- self._active_span.set_status(
- Status(status_code=StatusCode.ERROR, description=details)
- )
- return self._servicer_context.set_code(code)
-
- def set_details(self, details):
- self.details = details
- self._active_span.set_status(
- Status(status_code=StatusCode.ERROR, description=details)
- )
- return self._servicer_context.set_details(details)
-
-
-# pylint:disable=abstract-method
-# pylint:disable=no-self-use
-# pylint:disable=unused-argument
-class OpenTelemetryServerInterceptor(grpc.ServerInterceptor):
- """
- A gRPC server interceptor, to add OpenTelemetry.
-
- Usage::
-
- tracer = some OpenTelemetry tracer
-
- interceptors = [
- OpenTelemetryServerInterceptor(tracer),
- ]
-
- server = grpc.server(
- futures.ThreadPoolExecutor(max_workers=concurrency),
- interceptors = interceptors)
-
- """
-
- def __init__(self, tracer):
- self._tracer = tracer
- self._carrier_getter = DictGetter()
-
- @contextmanager
- def _set_remote_context(self, servicer_context):
- metadata = servicer_context.invocation_metadata()
- if metadata:
- md_dict = {md.key: md.value for md in metadata}
- ctx = propagators.extract(self._carrier_getter, md_dict)
- token = attach(ctx)
- try:
- yield
- finally:
- detach(token)
- else:
- yield
-
- def _start_span(self, handler_call_details, context):
-
- attributes = {
- "rpc.method": handler_call_details.method,
- "rpc.system": "grpc",
- "rpc.grpc.status_code": grpc.StatusCode.OK,
- }
-
- metadata = dict(context.invocation_metadata())
- if "user-agent" in metadata:
- attributes["rpc.user_agent"] = metadata["user-agent"]
-
- # Split up the peer to keep with how other telemetry sources
- # do it. This looks like:
- # * ipv6:[::1]:57284
- # * ipv4:127.0.0.1:57284
- # * ipv4:10.2.1.1:57284,127.0.0.1:57284
- #
- try:
- host, port = (
- context.peer().split(",")[0].split(":", 1)[1].rsplit(":", 1)
- )
-
- # other telemetry sources convert this, so we will too
- if host in ("[::1]", "127.0.0.1"):
- host = "localhost"
-
- attributes.update({"net.peer.name": host, "net.peer.port": port})
- except IndexError:
- logger.warning("Failed to parse peer address '%s'", context.peer())
-
- return self._tracer.start_as_current_span(
- name=handler_call_details.method,
- kind=trace.SpanKind.SERVER,
- attributes=attributes,
- )
-
- def intercept_service(self, continuation, handler_call_details):
- def telemetry_wrapper(behavior, request_streaming, response_streaming):
- def telemetry_interceptor(request_or_iterator, context):
-
- with self._set_remote_context(context):
- with self._start_span(
- handler_call_details, context
- ) as span:
- # wrap the context
- context = _OpenTelemetryServicerContext(context, span)
-
- # And now we run the actual RPC.
- try:
- return behavior(request_or_iterator, context)
- except Exception as error:
- # Bare exceptions are likely to be gRPC aborts, which
- # we handle in our context wrapper.
- # Here, we're interested in uncaught exceptions.
- # pylint:disable=unidiomatic-typecheck
- if type(error) != Exception:
- span.record_exception(error)
- raise error
-
- return telemetry_interceptor
-
- return _wrap_rpc_behavior(
- continuation(handler_call_details), telemetry_wrapper
- )
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_utilities.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_utilities.py
deleted file mode 100644
index 8cf1f957c31..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_utilities.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""Internal utilities."""
-
-from contextlib import contextmanager
-from time import time
-
-import grpc
-
-
-class RpcInfo:
- def __init__(
- self,
- full_method=None,
- metadata=None,
- timeout=None,
- request=None,
- response=None,
- error=None,
- ):
- self.full_method = full_method
- self.metadata = metadata
- self.timeout = timeout
- self.request = request
- self.response = response
- self.error = error
-
-
-class TimedMetricRecorder:
- def __init__(self, meter, span_kind):
- self._meter = meter
- service_name = "grpcio"
- self._span_kind = span_kind
-
- if self._meter:
- self._duration = self._meter.create_valuerecorder(
- name="{}/{}/duration".format(service_name, span_kind),
- description="Duration of grpc requests to the server",
- unit="ms",
- value_type=float,
- )
- self._error_count = self._meter.create_counter(
- name="{}/{}/errors".format(service_name, span_kind),
- description="Number of errors that were returned from the server",
- unit="1",
- value_type=int,
- )
- self._bytes_in = self._meter.create_counter(
- name="{}/{}/bytes_in".format(service_name, span_kind),
- description="Number of bytes received from the server",
- unit="by",
- value_type=int,
- )
- self._bytes_out = self._meter.create_counter(
- name="{}/{}/bytes_out".format(service_name, span_kind),
- description="Number of bytes sent out through gRPC",
- unit="by",
- value_type=int,
- )
-
- def record_bytes_in(self, bytes_in, method):
- if self._meter:
- labels = {"method": method}
- self._bytes_in.add(bytes_in, labels)
-
- def record_bytes_out(self, bytes_out, method):
- if self._meter:
- labels = {"method": method}
- self._bytes_out.add(bytes_out, labels)
-
- @contextmanager
- def record_latency(self, method):
- start_time = time()
- labels = {"method": method, "status_code": grpc.StatusCode.OK}
- try:
- yield labels
- except grpc.RpcError as exc:
- if self._meter:
- # pylint: disable=no-member
- labels["status_code"] = exc.code()
- self._error_count.add(1, labels)
- labels["error"] = True
- raise
- finally:
- if self._meter:
- if "error" not in labels:
- labels["error"] = False
- elapsed_time = (time() - start_time) * 1000
- self._duration.record(elapsed_time, labels)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/grpcext/__init__.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/grpcext/__init__.py
deleted file mode 100644
index d5e2549bab8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/grpcext/__init__.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# pylint:disable=import-outside-toplevel
-# pylint:disable=import-self
-# pylint:disable=no-name-in-module
-
-import abc
-
-
-class UnaryClientInfo(abc.ABC):
- """Consists of various information about a unary RPC on the
- invocation-side.
-
- Attributes:
- full_method: A string of the full RPC method, i.e.,
- /package.service/method.
- timeout: The length of time in seconds to wait for the computation to
- terminate or be cancelled, or None if this method should block until
- the computation is terminated or is cancelled no matter how long that
- takes.
- """
-
-
-class StreamClientInfo(abc.ABC):
- """Consists of various information about a stream RPC on the
- invocation-side.
-
- Attributes:
- full_method: A string of the full RPC method, i.e.,
- /package.service/method.
- is_client_stream: Indicates whether the RPC is client-streaming.
- is_server_stream: Indicates whether the RPC is server-streaming.
- timeout: The length of time in seconds to wait for the computation to
- terminate or be cancelled, or None if this method should block until
- the computation is terminated or is cancelled no matter how long that
- takes.
- """
-
-
-class UnaryClientInterceptor(abc.ABC):
- """Affords intercepting unary-unary RPCs on the invocation-side."""
-
- @abc.abstractmethod
- def intercept_unary(self, request, metadata, client_info, invoker):
- """Intercepts unary-unary RPCs on the invocation-side.
-
- Args:
- request: The request value for the RPC.
- metadata: Optional :term:`metadata` to be transmitted to the
- service-side of the RPC.
- client_info: A UnaryClientInfo containing various information about
- the RPC.
- invoker: The handler to complete the RPC on the client. It is the
- interceptor's responsibility to call it.
-
- Returns:
- The result from calling invoker(request, metadata).
- """
- raise NotImplementedError()
-
-
-class StreamClientInterceptor(abc.ABC):
- """Affords intercepting stream RPCs on the invocation-side."""
-
- @abc.abstractmethod
- def intercept_stream(
- self, request_or_iterator, metadata, client_info, invoker
- ):
- """Intercepts stream RPCs on the invocation-side.
-
- Args:
- request_or_iterator: The request value for the RPC if
- `client_info.is_client_stream` is `false`; otherwise, an iterator of
- request values.
- metadata: Optional :term:`metadata` to be transmitted to the service-side
- of the RPC.
- client_info: A StreamClientInfo containing various information about
- the RPC.
- invoker: The handler to complete the RPC on the client. It is the
- interceptor's responsibility to call it.
-
- Returns:
- The result from calling invoker(metadata).
- """
- raise NotImplementedError()
-
-
-def intercept_channel(channel, *interceptors):
- """Creates an intercepted channel.
-
- Args:
- channel: A Channel.
- interceptors: Zero or more UnaryClientInterceptors or
- StreamClientInterceptors
-
- Returns:
- A Channel.
-
- Raises:
- TypeError: If an interceptor derives from neither UnaryClientInterceptor
- nor StreamClientInterceptor.
- """
- from . import _interceptor
-
- return _interceptor.intercept_channel(channel, *interceptors)
-
-
-__all__ = (
- "UnaryClientInterceptor",
- "StreamClientInfo",
- "StreamClientInterceptor",
- "intercept_channel",
-)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/grpcext/_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/grpcext/_interceptor.py
deleted file mode 100644
index b9f74fff805..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/grpcext/_interceptor.py
+++ /dev/null
@@ -1,254 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# pylint:disable=relative-beyond-top-level
-# pylint:disable=arguments-differ
-# pylint:disable=no-member
-# pylint:disable=signature-differs
-
-"""Implementation of gRPC Python interceptors."""
-
-
-import collections
-
-import grpc
-
-from .. import grpcext
-
-
-class _UnaryClientInfo(
- collections.namedtuple("_UnaryClientInfo", ("full_method", "timeout"))
-):
- pass
-
-
-class _StreamClientInfo(
- collections.namedtuple(
- "_StreamClientInfo",
- ("full_method", "is_client_stream", "is_server_stream", "timeout"),
- )
-):
- pass
-
-
-class _InterceptorUnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
- def __init__(self, method, base_callable, interceptor):
- self._method = method
- self._base_callable = base_callable
- self._interceptor = interceptor
-
- def __call__(self, request, timeout=None, metadata=None, credentials=None):
- def invoker(request, metadata):
- return self._base_callable(request, timeout, metadata, credentials)
-
- client_info = _UnaryClientInfo(self._method, timeout)
- return self._interceptor.intercept_unary(
- request, metadata, client_info, invoker
- )
-
- def with_call(
- self, request, timeout=None, metadata=None, credentials=None
- ):
- def invoker(request, metadata):
- return self._base_callable.with_call(
- request, timeout, metadata, credentials
- )
-
- client_info = _UnaryClientInfo(self._method, timeout)
- return self._interceptor.intercept_unary(
- request, metadata, client_info, invoker
- )
-
- def future(self, request, timeout=None, metadata=None, credentials=None):
- def invoker(request, metadata):
- return self._base_callable.future(
- request, timeout, metadata, credentials
- )
-
- client_info = _UnaryClientInfo(self._method, timeout)
- return self._interceptor.intercept_unary(
- request, metadata, client_info, invoker
- )
-
-
-class _InterceptorUnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable):
- def __init__(self, method, base_callable, interceptor):
- self._method = method
- self._base_callable = base_callable
- self._interceptor = interceptor
-
- def __call__(self, request, timeout=None, metadata=None, credentials=None):
- def invoker(request, metadata):
- return self._base_callable(request, timeout, metadata, credentials)
-
- client_info = _StreamClientInfo(self._method, False, True, timeout)
- return self._interceptor.intercept_stream(
- request, metadata, client_info, invoker
- )
-
-
-class _InterceptorStreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
- def __init__(self, method, base_callable, interceptor):
- self._method = method
- self._base_callable = base_callable
- self._interceptor = interceptor
-
- def __call__(
- self, request_iterator, timeout=None, metadata=None, credentials=None
- ):
- def invoker(request_iterator, metadata):
- return self._base_callable(
- request_iterator, timeout, metadata, credentials
- )
-
- client_info = _StreamClientInfo(self._method, True, False, timeout)
- return self._interceptor.intercept_stream(
- request_iterator, metadata, client_info, invoker
- )
-
- def with_call(
- self, request_iterator, timeout=None, metadata=None, credentials=None
- ):
- def invoker(request_iterator, metadata):
- return self._base_callable.with_call(
- request_iterator, timeout, metadata, credentials
- )
-
- client_info = _StreamClientInfo(self._method, True, False, timeout)
- return self._interceptor.intercept_stream(
- request_iterator, metadata, client_info, invoker
- )
-
- def future(
- self, request_iterator, timeout=None, metadata=None, credentials=None
- ):
- def invoker(request_iterator, metadata):
- return self._base_callable.future(
- request_iterator, timeout, metadata, credentials
- )
-
- client_info = _StreamClientInfo(self._method, True, False, timeout)
- return self._interceptor.intercept_stream(
- request_iterator, metadata, client_info, invoker
- )
-
-
-class _InterceptorStreamStreamMultiCallable(grpc.StreamStreamMultiCallable):
- def __init__(self, method, base_callable, interceptor):
- self._method = method
- self._base_callable = base_callable
- self._interceptor = interceptor
-
- def __call__(
- self, request_iterator, timeout=None, metadata=None, credentials=None
- ):
- def invoker(request_iterator, metadata):
- return self._base_callable(
- request_iterator, timeout, metadata, credentials
- )
-
- client_info = _StreamClientInfo(self._method, True, True, timeout)
- return self._interceptor.intercept_stream(
- request_iterator, metadata, client_info, invoker
- )
-
-
-class _InterceptorChannel(grpc.Channel):
- def __init__(self, channel, interceptor):
- self._channel = channel
- self._interceptor = interceptor
-
- def subscribe(self, *args, **kwargs):
- self._channel.subscribe(*args, **kwargs)
-
- def unsubscribe(self, *args, **kwargs):
- self._channel.unsubscribe(*args, **kwargs)
-
- def unary_unary(
- self, method, request_serializer=None, response_deserializer=None
- ):
- base_callable = self._channel.unary_unary(
- method, request_serializer, response_deserializer
- )
- if isinstance(self._interceptor, grpcext.UnaryClientInterceptor):
- return _InterceptorUnaryUnaryMultiCallable(
- method, base_callable, self._interceptor
- )
- return base_callable
-
- def unary_stream(
- self, method, request_serializer=None, response_deserializer=None
- ):
- base_callable = self._channel.unary_stream(
- method, request_serializer, response_deserializer
- )
- if isinstance(self._interceptor, grpcext.StreamClientInterceptor):
- return _InterceptorUnaryStreamMultiCallable(
- method, base_callable, self._interceptor
- )
- return base_callable
-
- def stream_unary(
- self, method, request_serializer=None, response_deserializer=None
- ):
- base_callable = self._channel.stream_unary(
- method, request_serializer, response_deserializer
- )
- if isinstance(self._interceptor, grpcext.StreamClientInterceptor):
- return _InterceptorStreamUnaryMultiCallable(
- method, base_callable, self._interceptor
- )
- return base_callable
-
- def stream_stream(
- self, method, request_serializer=None, response_deserializer=None
- ):
- base_callable = self._channel.stream_stream(
- method, request_serializer, response_deserializer
- )
- if isinstance(self._interceptor, grpcext.StreamClientInterceptor):
- return _InterceptorStreamStreamMultiCallable(
- method, base_callable, self._interceptor
- )
- return base_callable
-
- def close(self):
- if not hasattr(self._channel, "close"):
- raise RuntimeError(
- "close() is not supported with the installed version of grpcio"
- )
- self._channel.close()
-
- def __enter__(self):
- """Enters the runtime context related to the channel object."""
- raise NotImplementedError()
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- """Exits the runtime context related to the channel object."""
- raise NotImplementedError()
-
-
-def intercept_channel(channel, *interceptors):
- result = channel
- for interceptor in interceptors:
- if not isinstance(
- interceptor, grpcext.UnaryClientInterceptor
- ) and not isinstance(interceptor, grpcext.StreamClientInterceptor):
- raise TypeError(
- "interceptor must be either a "
- "grpcext.UnaryClientInterceptor or a "
- "grpcext.StreamClientInterceptor"
- )
- result = _InterceptorChannel(result, interceptor)
- return result
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/version.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/__init__.py
deleted file mode 100644
index b0a6f428417..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright The OpenTelemetry 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/instrumentation/opentelemetry-instrumentation-grpc/tests/_client.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/_client.py
deleted file mode 100644
index 43310b5f651..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/_client.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright The OpenTelemetry 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 .protobuf.test_server_pb2 import Request
-
-CLIENT_ID = 1
-
-
-def simple_method(stub, error=False):
- request = Request(
- client_id=CLIENT_ID, request_data="error" if error else "data"
- )
- stub.SimpleMethod(request)
-
-
-def client_streaming_method(stub, error=False):
- # create a generator
- def request_messages():
- for _ in range(5):
- request = Request(
- client_id=CLIENT_ID, request_data="error" if error else "data"
- )
- yield request
-
- stub.ClientStreamingMethod(request_messages())
-
-
-def server_streaming_method(stub, error=False):
- request = Request(
- client_id=CLIENT_ID, request_data="error" if error else "data"
- )
- response_iterator = stub.ServerStreamingMethod(request)
- list(response_iterator)
-
-
-def bidirectional_streaming_method(stub, error=False):
- def request_messages():
- for _ in range(5):
- request = Request(
- client_id=CLIENT_ID, request_data="error" if error else "data"
- )
- yield request
-
- response_iterator = stub.BidirectionalStreamingMethod(request_messages())
-
- list(response_iterator)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/_server.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/_server.py
deleted file mode 100644
index a4e1c266b8a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/_server.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright The OpenTelemetry 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 concurrent import futures
-
-import grpc
-
-from .protobuf import test_server_pb2, test_server_pb2_grpc
-
-SERVER_ID = 1
-
-
-class TestServer(test_server_pb2_grpc.GRPCTestServerServicer):
- def SimpleMethod(self, request, context):
- if request.request_data == "error":
- context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
- return test_server_pb2.Response()
- response = test_server_pb2.Response(
- server_id=SERVER_ID, response_data="data"
- )
- return response
-
- def ClientStreamingMethod(self, request_iterator, context):
- data = list(request_iterator)
- if data[0].request_data == "error":
- context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
- return test_server_pb2.Response()
- response = test_server_pb2.Response(
- server_id=SERVER_ID, response_data="data"
- )
- return response
-
- def ServerStreamingMethod(self, request, context):
- if request.request_data == "error":
-
- context.abort(
- code=grpc.StatusCode.INVALID_ARGUMENT,
- details="server stream error",
- )
- return test_server_pb2.Response()
-
- # create a generator
- def response_messages():
- for _ in range(5):
- response = test_server_pb2.Response(
- server_id=SERVER_ID, response_data="data"
- )
- yield response
-
- return response_messages()
-
- def BidirectionalStreamingMethod(self, request_iterator, context):
- data = list(request_iterator)
- if data[0].request_data == "error":
- context.abort(
- code=grpc.StatusCode.INVALID_ARGUMENT,
- details="bidirectional error",
- )
- return
-
- for _ in range(5):
- yield test_server_pb2.Response(
- server_id=SERVER_ID, response_data="data"
- )
-
-
-def create_test_server(port):
- server = grpc.server(futures.ThreadPoolExecutor(max_workers=1))
-
- test_server_pb2_grpc.add_GRPCTestServerServicer_to_server(
- TestServer(), server
- )
-
- server.add_insecure_port("localhost:{}".format(port))
-
- return server
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server.proto b/instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server.proto
deleted file mode 100644
index 790a7675de0..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server.proto
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2019 gRPC 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.
-syntax = "proto3";
-
-message Request {
- int64 client_id = 1;
- string request_data = 2;
-}
-
-message Response {
- int64 server_id = 1;
- string response_data = 2;
-}
-
-service GRPCTestServer {
- rpc SimpleMethod (Request) returns (Response);
-
- rpc ClientStreamingMethod (stream Request) returns (Response);
-
- rpc ServerStreamingMethod (Request) returns (stream Response);
-
- rpc BidirectionalStreamingMethod (stream Request) returns (stream Response);
-}
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server_pb2.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server_pb2.py
deleted file mode 100644
index 735206f8505..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server_pb2.py
+++ /dev/null
@@ -1,215 +0,0 @@
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: test_server.proto
-
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name="test_server.proto",
- package="",
- syntax="proto3",
- serialized_options=None,
- serialized_pb=b'\n\x11test_server.proto"2\n\x07Request\x12\x11\n\tclient_id\x18\x01 \x01(\x03\x12\x14\n\x0crequest_data\x18\x02 \x01(\t"4\n\x08Response\x12\x11\n\tserver_id\x18\x01 \x01(\x03\x12\x15\n\rresponse_data\x18\x02 \x01(\t2\xce\x01\n\x0eGRPCTestServer\x12#\n\x0cSimpleMethod\x12\x08.Request\x1a\t.Response\x12.\n\x15\x43lientStreamingMethod\x12\x08.Request\x1a\t.Response(\x01\x12.\n\x15ServerStreamingMethod\x12\x08.Request\x1a\t.Response0\x01\x12\x37\n\x1c\x42idirectionalStreamingMethod\x12\x08.Request\x1a\t.Response(\x01\x30\x01\x62\x06proto3',
-)
-
-
-_REQUEST = _descriptor.Descriptor(
- name="Request",
- full_name="Request",
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name="client_id",
- full_name="Request.client_id",
- index=0,
- number=1,
- type=3,
- cpp_type=2,
- label=1,
- has_default_value=False,
- default_value=0,
- message_type=None,
- enum_type=None,
- containing_type=None,
- is_extension=False,
- extension_scope=None,
- serialized_options=None,
- file=DESCRIPTOR,
- ),
- _descriptor.FieldDescriptor(
- name="request_data",
- full_name="Request.request_data",
- index=1,
- number=2,
- type=9,
- cpp_type=9,
- label=1,
- has_default_value=False,
- default_value=b"".decode("utf-8"),
- message_type=None,
- enum_type=None,
- containing_type=None,
- is_extension=False,
- extension_scope=None,
- serialized_options=None,
- file=DESCRIPTOR,
- ),
- ],
- extensions=[],
- nested_types=[],
- enum_types=[],
- serialized_options=None,
- is_extendable=False,
- syntax="proto3",
- extension_ranges=[],
- oneofs=[],
- serialized_start=21,
- serialized_end=71,
-)
-
-
-_RESPONSE = _descriptor.Descriptor(
- name="Response",
- full_name="Response",
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name="server_id",
- full_name="Response.server_id",
- index=0,
- number=1,
- type=3,
- cpp_type=2,
- label=1,
- has_default_value=False,
- default_value=0,
- message_type=None,
- enum_type=None,
- containing_type=None,
- is_extension=False,
- extension_scope=None,
- serialized_options=None,
- file=DESCRIPTOR,
- ),
- _descriptor.FieldDescriptor(
- name="response_data",
- full_name="Response.response_data",
- index=1,
- number=2,
- type=9,
- cpp_type=9,
- label=1,
- has_default_value=False,
- default_value=b"".decode("utf-8"),
- message_type=None,
- enum_type=None,
- containing_type=None,
- is_extension=False,
- extension_scope=None,
- serialized_options=None,
- file=DESCRIPTOR,
- ),
- ],
- extensions=[],
- nested_types=[],
- enum_types=[],
- serialized_options=None,
- is_extendable=False,
- syntax="proto3",
- extension_ranges=[],
- oneofs=[],
- serialized_start=73,
- serialized_end=125,
-)
-
-DESCRIPTOR.message_types_by_name["Request"] = _REQUEST
-DESCRIPTOR.message_types_by_name["Response"] = _RESPONSE
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-Request = _reflection.GeneratedProtocolMessageType(
- "Request",
- (_message.Message,),
- {
- "DESCRIPTOR": _REQUEST,
- "__module__": "test_server_pb2"
- # @@protoc_insertion_point(class_scope:Request)
- },
-)
-_sym_db.RegisterMessage(Request)
-
-Response = _reflection.GeneratedProtocolMessageType(
- "Response",
- (_message.Message,),
- {
- "DESCRIPTOR": _RESPONSE,
- "__module__": "test_server_pb2"
- # @@protoc_insertion_point(class_scope:Response)
- },
-)
-_sym_db.RegisterMessage(Response)
-
-
-_GRPCTESTSERVER = _descriptor.ServiceDescriptor(
- name="GRPCTestServer",
- full_name="GRPCTestServer",
- file=DESCRIPTOR,
- index=0,
- serialized_options=None,
- serialized_start=128,
- serialized_end=334,
- methods=[
- _descriptor.MethodDescriptor(
- name="SimpleMethod",
- full_name="GRPCTestServer.SimpleMethod",
- index=0,
- containing_service=None,
- input_type=_REQUEST,
- output_type=_RESPONSE,
- serialized_options=None,
- ),
- _descriptor.MethodDescriptor(
- name="ClientStreamingMethod",
- full_name="GRPCTestServer.ClientStreamingMethod",
- index=1,
- containing_service=None,
- input_type=_REQUEST,
- output_type=_RESPONSE,
- serialized_options=None,
- ),
- _descriptor.MethodDescriptor(
- name="ServerStreamingMethod",
- full_name="GRPCTestServer.ServerStreamingMethod",
- index=2,
- containing_service=None,
- input_type=_REQUEST,
- output_type=_RESPONSE,
- serialized_options=None,
- ),
- _descriptor.MethodDescriptor(
- name="BidirectionalStreamingMethod",
- full_name="GRPCTestServer.BidirectionalStreamingMethod",
- index=3,
- containing_service=None,
- input_type=_REQUEST,
- output_type=_RESPONSE,
- serialized_options=None,
- ),
- ],
-)
-_sym_db.RegisterServiceDescriptor(_GRPCTESTSERVER)
-
-DESCRIPTOR.services_by_name["GRPCTestServer"] = _GRPCTESTSERVER
-
-# @@protoc_insertion_point(module_scope)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server_pb2_grpc.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server_pb2_grpc.py
deleted file mode 100644
index d0a6fd5184f..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server_pb2_grpc.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
-import grpc
-
-from tests.protobuf import test_server_pb2 as test__server__pb2
-
-
-class GRPCTestServerStub(object):
- """Missing associated documentation comment in .proto file"""
-
- def __init__(self, channel):
- """Constructor.
-
- Args:
- channel: A grpc.Channel.
- """
- self.SimpleMethod = channel.unary_unary(
- "/GRPCTestServer/SimpleMethod",
- request_serializer=test__server__pb2.Request.SerializeToString,
- response_deserializer=test__server__pb2.Response.FromString,
- )
- self.ClientStreamingMethod = channel.stream_unary(
- "/GRPCTestServer/ClientStreamingMethod",
- request_serializer=test__server__pb2.Request.SerializeToString,
- response_deserializer=test__server__pb2.Response.FromString,
- )
- self.ServerStreamingMethod = channel.unary_stream(
- "/GRPCTestServer/ServerStreamingMethod",
- request_serializer=test__server__pb2.Request.SerializeToString,
- response_deserializer=test__server__pb2.Response.FromString,
- )
- self.BidirectionalStreamingMethod = channel.stream_stream(
- "/GRPCTestServer/BidirectionalStreamingMethod",
- request_serializer=test__server__pb2.Request.SerializeToString,
- response_deserializer=test__server__pb2.Response.FromString,
- )
-
-
-class GRPCTestServerServicer(object):
- """Missing associated documentation comment in .proto file"""
-
- def SimpleMethod(self, request, context):
- """Missing associated documentation comment in .proto file"""
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details("Method not implemented!")
- raise NotImplementedError("Method not implemented!")
-
- def ClientStreamingMethod(self, request_iterator, context):
- """Missing associated documentation comment in .proto file"""
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details("Method not implemented!")
- raise NotImplementedError("Method not implemented!")
-
- def ServerStreamingMethod(self, request, context):
- """Missing associated documentation comment in .proto file"""
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details("Method not implemented!")
- raise NotImplementedError("Method not implemented!")
-
- def BidirectionalStreamingMethod(self, request_iterator, context):
- """Missing associated documentation comment in .proto file"""
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details("Method not implemented!")
- raise NotImplementedError("Method not implemented!")
-
-
-def add_GRPCTestServerServicer_to_server(servicer, server):
- rpc_method_handlers = {
- "SimpleMethod": grpc.unary_unary_rpc_method_handler(
- servicer.SimpleMethod,
- request_deserializer=test__server__pb2.Request.FromString,
- response_serializer=test__server__pb2.Response.SerializeToString,
- ),
- "ClientStreamingMethod": grpc.stream_unary_rpc_method_handler(
- servicer.ClientStreamingMethod,
- request_deserializer=test__server__pb2.Request.FromString,
- response_serializer=test__server__pb2.Response.SerializeToString,
- ),
- "ServerStreamingMethod": grpc.unary_stream_rpc_method_handler(
- servicer.ServerStreamingMethod,
- request_deserializer=test__server__pb2.Request.FromString,
- response_serializer=test__server__pb2.Response.SerializeToString,
- ),
- "BidirectionalStreamingMethod": grpc.stream_stream_rpc_method_handler(
- servicer.BidirectionalStreamingMethod,
- request_deserializer=test__server__pb2.Request.FromString,
- response_serializer=test__server__pb2.Response.SerializeToString,
- ),
- }
- generic_handler = grpc.method_handlers_generic_handler(
- "GRPCTestServer", rpc_method_handlers
- )
- server.add_generic_rpc_handlers((generic_handler,))
-
-
-# This class is part of an EXPERIMENTAL API.
-class GRPCTestServer(object):
- """Missing associated documentation comment in .proto file"""
-
- @staticmethod
- def SimpleMethod(
- request,
- target,
- options=(),
- channel_credentials=None,
- call_credentials=None,
- compression=None,
- wait_for_ready=None,
- timeout=None,
- metadata=None,
- ):
- return grpc.experimental.unary_unary(
- request,
- target,
- "/GRPCTestServer/SimpleMethod",
- test__server__pb2.Request.SerializeToString,
- test__server__pb2.Response.FromString,
- options,
- channel_credentials,
- call_credentials,
- compression,
- wait_for_ready,
- timeout,
- metadata,
- )
-
- @staticmethod
- def ClientStreamingMethod(
- request_iterator,
- target,
- options=(),
- channel_credentials=None,
- call_credentials=None,
- compression=None,
- wait_for_ready=None,
- timeout=None,
- metadata=None,
- ):
- return grpc.experimental.stream_unary(
- request_iterator,
- target,
- "/GRPCTestServer/ClientStreamingMethod",
- test__server__pb2.Request.SerializeToString,
- test__server__pb2.Response.FromString,
- options,
- channel_credentials,
- call_credentials,
- compression,
- wait_for_ready,
- timeout,
- metadata,
- )
-
- @staticmethod
- def ServerStreamingMethod(
- request,
- target,
- options=(),
- channel_credentials=None,
- call_credentials=None,
- compression=None,
- wait_for_ready=None,
- timeout=None,
- metadata=None,
- ):
- return grpc.experimental.unary_stream(
- request,
- target,
- "/GRPCTestServer/ServerStreamingMethod",
- test__server__pb2.Request.SerializeToString,
- test__server__pb2.Response.FromString,
- options,
- channel_credentials,
- call_credentials,
- compression,
- wait_for_ready,
- timeout,
- metadata,
- )
-
- @staticmethod
- def BidirectionalStreamingMethod(
- request_iterator,
- target,
- options=(),
- channel_credentials=None,
- call_credentials=None,
- compression=None,
- wait_for_ready=None,
- timeout=None,
- metadata=None,
- ):
- return grpc.experimental.stream_stream(
- request_iterator,
- target,
- "/GRPCTestServer/BidirectionalStreamingMethod",
- test__server__pb2.Request.SerializeToString,
- test__server__pb2.Response.FromString,
- options,
- channel_credentials,
- call_credentials,
- compression,
- wait_for_ready,
- timeout,
- metadata,
- )
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py
deleted file mode 100644
index f351c6fdd46..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py
+++ /dev/null
@@ -1,295 +0,0 @@
-# Copyright The OpenTelemetry 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 grpc
-
-import opentelemetry.instrumentation.grpc
-from opentelemetry import trace
-from opentelemetry.instrumentation.grpc import GrpcInstrumentorClient
-from opentelemetry.sdk.metrics.export.aggregate import (
- MinMaxSumCountAggregator,
- SumAggregator,
-)
-from opentelemetry.test.test_base import TestBase
-from tests.protobuf import test_server_pb2_grpc
-
-from ._client import (
- bidirectional_streaming_method,
- client_streaming_method,
- server_streaming_method,
- simple_method,
-)
-from ._server import create_test_server
-
-
-class TestClientProto(TestBase):
- def setUp(self):
- super().setUp()
- GrpcInstrumentorClient().instrument(
- exporter=self.memory_metrics_exporter
- )
- self.server = create_test_server(25565)
- self.server.start()
- self.channel = grpc.insecure_channel("localhost:25565")
- self._stub = test_server_pb2_grpc.GRPCTestServerStub(self.channel)
-
- def tearDown(self):
- super().tearDown()
- GrpcInstrumentorClient().uninstrument()
- self.memory_metrics_exporter.clear()
- self.server.stop(None)
- self.channel.close()
-
- def _verify_success_records(self, num_bytes_out, num_bytes_in, method):
- # pylint: disable=protected-access,no-member
- self.channel._interceptor.controller.tick()
- records = self.memory_metrics_exporter.get_exported_metrics()
- self.assertEqual(len(records), 3)
-
- bytes_out = None
- bytes_in = None
- duration = None
-
- for record in records:
- if record.instrument.name == "grpcio/client/duration":
- duration = record
- elif record.instrument.name == "grpcio/client/bytes_out":
- bytes_out = record
- elif record.instrument.name == "grpcio/client/bytes_in":
- bytes_in = record
-
- self.assertIsNotNone(bytes_out)
- self.assertEqual(bytes_out.instrument.name, "grpcio/client/bytes_out")
- self.assertEqual(bytes_out.labels, (("method", method),))
-
- self.assertIsNotNone(bytes_in)
- self.assertEqual(bytes_in.instrument.name, "grpcio/client/bytes_in")
- self.assertEqual(bytes_in.labels, (("method", method),))
-
- self.assertIsNotNone(duration)
- self.assertEqual(duration.instrument.name, "grpcio/client/duration")
- self.assertEqual(
- duration.labels,
- (
- ("error", False),
- ("method", method),
- ("status_code", grpc.StatusCode.OK),
- ),
- )
-
- self.assertEqual(type(bytes_out.aggregator), SumAggregator)
- self.assertEqual(type(bytes_in.aggregator), SumAggregator)
- self.assertEqual(type(duration.aggregator), MinMaxSumCountAggregator)
-
- self.assertEqual(bytes_out.aggregator.checkpoint, num_bytes_out)
- self.assertEqual(bytes_in.aggregator.checkpoint, num_bytes_in)
-
- self.assertEqual(duration.aggregator.checkpoint.count, 1)
- self.assertGreaterEqual(duration.aggregator.checkpoint.sum, 0)
-
- def test_unary_unary(self):
- simple_method(self._stub)
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
-
- self.assertEqual(span.name, "/GRPCTestServer/SimpleMethod")
- self.assertIs(span.kind, trace.SpanKind.CLIENT)
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.grpc
- )
-
- self._verify_success_records(8, 8, "/GRPCTestServer/SimpleMethod")
-
- def test_unary_stream(self):
- server_streaming_method(self._stub)
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
-
- self.assertEqual(span.name, "/GRPCTestServer/ServerStreamingMethod")
- self.assertIs(span.kind, trace.SpanKind.CLIENT)
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.grpc
- )
-
- self._verify_success_records(
- 8, 40, "/GRPCTestServer/ServerStreamingMethod"
- )
-
- def test_stream_unary(self):
- client_streaming_method(self._stub)
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
-
- self.assertEqual(span.name, "/GRPCTestServer/ClientStreamingMethod")
- self.assertIs(span.kind, trace.SpanKind.CLIENT)
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.grpc
- )
-
- self._verify_success_records(
- 40, 8, "/GRPCTestServer/ClientStreamingMethod"
- )
-
- def test_stream_stream(self):
- bidirectional_streaming_method(self._stub)
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
-
- self.assertEqual(
- span.name, "/GRPCTestServer/BidirectionalStreamingMethod"
- )
- self.assertIs(span.kind, trace.SpanKind.CLIENT)
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.grpc
- )
-
- self._verify_success_records(
- 40, 40, "/GRPCTestServer/BidirectionalStreamingMethod"
- )
-
- def _verify_error_records(self, method):
- # pylint: disable=protected-access,no-member
- self.channel._interceptor.controller.tick()
- records = self.memory_metrics_exporter.get_exported_metrics()
- self.assertEqual(len(records), 3)
-
- bytes_out = None
- errors = None
- duration = None
-
- for record in records:
- if record.instrument.name == "grpcio/client/duration":
- duration = record
- elif record.instrument.name == "grpcio/client/bytes_out":
- bytes_out = record
- elif record.instrument.name == "grpcio/client/errors":
- errors = record
-
- self.assertIsNotNone(bytes_out)
- self.assertIsNotNone(errors)
- self.assertIsNotNone(duration)
-
- self.assertEqual(errors.instrument.name, "grpcio/client/errors")
- self.assertEqual(
- errors.labels,
- (
- ("method", method),
- ("status_code", grpc.StatusCode.INVALID_ARGUMENT),
- ),
- )
- self.assertEqual(errors.aggregator.checkpoint, 1)
-
- self.assertEqual(
- duration.labels,
- (
- ("error", True),
- ("method", method),
- ("status_code", grpc.StatusCode.INVALID_ARGUMENT),
- ),
- )
-
- def test_error_simple(self):
- with self.assertRaises(grpc.RpcError):
- simple_method(self._stub, error=True)
-
- self._verify_error_records("/GRPCTestServer/SimpleMethod")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self.assertIs(
- span.status.status_code, trace.status.StatusCode.ERROR,
- )
-
- def test_error_stream_unary(self):
- with self.assertRaises(grpc.RpcError):
- client_streaming_method(self._stub, error=True)
-
- self._verify_error_records("/GRPCTestServer/ClientStreamingMethod")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self.assertIs(
- span.status.status_code, trace.status.StatusCode.ERROR,
- )
-
- def test_error_unary_stream(self):
- with self.assertRaises(grpc.RpcError):
- server_streaming_method(self._stub, error=True)
-
- self._verify_error_records("/GRPCTestServer/ServerStreamingMethod")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self.assertIs(
- span.status.status_code, trace.status.StatusCode.ERROR,
- )
-
- def test_error_stream_stream(self):
- with self.assertRaises(grpc.RpcError):
- bidirectional_streaming_method(self._stub, error=True)
-
- self._verify_error_records(
- "/GRPCTestServer/BidirectionalStreamingMethod"
- )
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self.assertIs(
- span.status.status_code, trace.status.StatusCode.ERROR,
- )
-
-
-class TestClientNoMetrics(TestBase):
- def setUp(self):
- super().setUp()
- GrpcInstrumentorClient().instrument()
- self.server = create_test_server(25565)
- self.server.start()
- self.channel = grpc.insecure_channel("localhost:25565")
- self._stub = test_server_pb2_grpc.GRPCTestServerStub(self.channel)
-
- def tearDown(self):
- super().tearDown()
- GrpcInstrumentorClient().uninstrument()
- self.memory_metrics_exporter.clear()
- self.server.stop(None)
-
- def test_unary_unary(self):
- simple_method(self._stub)
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
-
- self.assertEqual(span.name, "/GRPCTestServer/SimpleMethod")
- self.assertIs(span.kind, trace.SpanKind.CLIENT)
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.grpc
- )
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py
deleted file mode 100644
index 13b535d8414..00000000000
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py
+++ /dev/null
@@ -1,295 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# pylint:disable=unused-argument
-# pylint:disable=no-self-use
-
-import threading
-from concurrent import futures
-
-import grpc
-
-import opentelemetry.instrumentation.grpc
-from opentelemetry import trace
-from opentelemetry.instrumentation.grpc import (
- GrpcInstrumentorServer,
- server_interceptor,
-)
-from opentelemetry.sdk import trace as trace_sdk
-from opentelemetry.test.test_base import TestBase
-
-
-class UnaryUnaryMethodHandler(grpc.RpcMethodHandler):
- def __init__(self, handler):
- self.request_streaming = False
- self.response_streaming = False
- self.request_deserializer = None
- self.response_serializer = None
- self.unary_unary = handler
- self.unary_stream = None
- self.stream_unary = None
- self.stream_stream = None
-
-
-class UnaryUnaryRpcHandler(grpc.GenericRpcHandler):
- def __init__(self, handler):
- self._unary_unary_handler = handler
-
- def service(self, handler_call_details):
- return UnaryUnaryMethodHandler(self._unary_unary_handler)
-
-
-class TestOpenTelemetryServerInterceptor(TestBase):
- def test_instrumentor(self):
- def handler(request, context):
- return b""
-
- grpc_server_instrumentor = GrpcInstrumentorServer()
- grpc_server_instrumentor.instrument()
- server = grpc.server(
- futures.ThreadPoolExecutor(max_workers=1),
- options=(("grpc.so_reuseport", 0),),
- )
-
- server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),))
-
- port = server.add_insecure_port("[::]:0")
- channel = grpc.insecure_channel("localhost:{:d}".format(port))
-
- try:
- server.start()
- channel.unary_unary("test")(b"test")
- finally:
- server.stop(None)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(span.name, "test")
- self.assertIs(span.kind, trace.SpanKind.SERVER)
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.grpc
- )
- grpc_server_instrumentor.uninstrument()
-
- def test_uninstrument(self):
- def handler(request, context):
- return b""
-
- grpc_server_instrumentor = GrpcInstrumentorServer()
- grpc_server_instrumentor.instrument()
- grpc_server_instrumentor.uninstrument()
- server = grpc.server(
- futures.ThreadPoolExecutor(max_workers=1),
- options=(("grpc.so_reuseport", 0),),
- )
-
- server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),))
-
- port = server.add_insecure_port("[::]:0")
- channel = grpc.insecure_channel("localhost:{:d}".format(port))
-
- try:
- server.start()
- channel.unary_unary("test")(b"test")
- finally:
- server.stop(None)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 0)
-
- def test_create_span(self):
- """Check that the interceptor wraps calls with spans server-side."""
-
- # Intercept gRPC calls...
- interceptor = server_interceptor()
-
- # No-op RPC handler
- def handler(request, context):
- return b""
-
- server = grpc.server(
- futures.ThreadPoolExecutor(max_workers=1),
- options=(("grpc.so_reuseport", 0),),
- interceptors=[interceptor],
- )
-
- server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),))
-
- port = server.add_insecure_port("[::]:0")
- channel = grpc.insecure_channel("localhost:{:d}".format(port))
-
- try:
- server.start()
- channel.unary_unary("")(b"")
- finally:
- server.stop(None)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- self.assertEqual(span.name, "")
- self.assertIs(span.kind, trace.SpanKind.SERVER)
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.grpc
- )
-
- def test_span_lifetime(self):
- """Check that the span is active for the duration of the call."""
-
- interceptor = server_interceptor()
-
- # To capture the current span at the time the handler is called
- active_span_in_handler = None
-
- def handler(request, context):
- nonlocal active_span_in_handler
- active_span_in_handler = trace.get_current_span()
- return b""
-
- server = grpc.server(
- futures.ThreadPoolExecutor(max_workers=1),
- options=(("grpc.so_reuseport", 0),),
- interceptors=[interceptor],
- )
- server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),))
-
- port = server.add_insecure_port("[::]:0")
- channel = grpc.insecure_channel("localhost:{:d}".format(port))
-
- active_span_before_call = trace.get_current_span()
- try:
- server.start()
- channel.unary_unary("")(b"")
- finally:
- server.stop(None)
- active_span_after_call = trace.get_current_span()
-
- self.assertEqual(active_span_before_call, trace.INVALID_SPAN)
- self.assertEqual(active_span_after_call, trace.INVALID_SPAN)
- self.assertIsInstance(active_span_in_handler, trace_sdk.Span)
- self.assertIsNone(active_span_in_handler.parent)
-
- def test_sequential_server_spans(self):
- """Check that sequential RPCs get separate server spans."""
-
- interceptor = server_interceptor()
-
- # Capture the currently active span in each thread
- active_spans_in_handler = []
-
- def handler(request, context):
- active_spans_in_handler.append(trace.get_current_span())
- return b""
-
- server = grpc.server(
- futures.ThreadPoolExecutor(max_workers=1),
- options=(("grpc.so_reuseport", 0),),
- interceptors=[interceptor],
- )
- server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),))
-
- port = server.add_insecure_port("[::]:0")
- channel = grpc.insecure_channel("localhost:{:d}".format(port))
-
- try:
- server.start()
- channel.unary_unary("")(b"")
- channel.unary_unary("")(b"")
- finally:
- server.stop(None)
-
- self.assertEqual(len(active_spans_in_handler), 2)
- # pylint:disable=unbalanced-tuple-unpacking
- span1, span2 = active_spans_in_handler
- # Spans should belong to separate traces, and each should be a root
- # span
- self.assertNotEqual(span1.context.span_id, span2.context.span_id)
- self.assertNotEqual(span1.context.trace_id, span2.context.trace_id)
- self.assertIsNone(span1.parent)
- self.assertIsNone(span1.parent)
-
- def test_concurrent_server_spans(self):
- """Check that concurrent RPC calls don't interfere with each other.
-
- This is the same check as test_sequential_server_spans except that the
- RPCs are concurrent. Two handlers are invoked at the same time on two
- separate threads. Each one should see a different active span and
- context.
- """
-
- interceptor = server_interceptor()
-
- # Capture the currently active span in each thread
- active_spans_in_handler = []
- latch = get_latch(2)
-
- def handler(request, context):
- latch()
- active_spans_in_handler.append(trace.get_current_span())
- return b""
-
- server = grpc.server(
- futures.ThreadPoolExecutor(max_workers=2),
- options=(("grpc.so_reuseport", 0),),
- interceptors=[interceptor],
- )
- server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),))
-
- port = server.add_insecure_port("[::]:0")
- channel = grpc.insecure_channel("localhost:{:d}".format(port))
-
- try:
- server.start()
- # Interleave calls so spans are active on each thread at the same
- # time
- with futures.ThreadPoolExecutor(max_workers=2) as tpe:
- f1 = tpe.submit(channel.unary_unary(""), b"")
- f2 = tpe.submit(channel.unary_unary(""), b"")
- futures.wait((f1, f2))
- finally:
- server.stop(None)
-
- self.assertEqual(len(active_spans_in_handler), 2)
- # pylint:disable=unbalanced-tuple-unpacking
- span1, span2 = active_spans_in_handler
- # Spans should belong to separate traces, and each should be a root
- # span
- self.assertNotEqual(span1.context.span_id, span2.context.span_id)
- self.assertNotEqual(span1.context.trace_id, span2.context.trace_id)
- self.assertIsNone(span1.parent)
- self.assertIsNone(span1.parent)
-
-
-def get_latch(num):
- """Get a countdown latch function for use in n threads."""
- cv = threading.Condition()
- count = 0
-
- def countdown_latch():
- """Block until n-1 other threads have called."""
- nonlocal count
- cv.acquire()
- count += 1
- cv.notify()
- cv.release()
- cv.acquire()
- while count < num:
- cv.wait()
- cv.release()
-
- return countdown_latch
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-jinja2/CHANGELOG.md
deleted file mode 100644
index b1f9ba50e11..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/CHANGELOG.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-jinja2
- ([#969](https://github.com/open-telemetry/opentelemetry-python/pull/969))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Add jinja2 instrumentation ([#643](https://github.com/open-telemetry/opentelemetry-python/pull/643))
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/LICENSE b/instrumentation/opentelemetry-instrumentation-jinja2/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-jinja2/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-jinja2/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/README.rst b/instrumentation/opentelemetry-instrumentation-jinja2/README.rst
deleted file mode 100644
index c74faeb32e1..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/README.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-OpenTelemetry jinja2 integration
-================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-jinja2.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-jinja2/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-jinja2
-
-
-References
-----------
-
-* `OpenTelemetry jinja2 integration `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/setup.cfg b/instrumentation/opentelemetry-instrumentation-jinja2/setup.cfg
deleted file mode 100644
index 08f46ae1058..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/setup.cfg
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-jinja2
-description = OpenTelemetry jinja2 instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-jinja2
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- jinja2~=2.7
- wrapt >= 1.0.0, < 2.0.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- jinja2 = opentelemetry.instrumentation.jinja2:Jinja2Instrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/setup.py b/instrumentation/opentelemetry-instrumentation-jinja2/setup.py
deleted file mode 100644
index e9d484e1ebc..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "jinja2", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/src/opentelemetry/instrumentation/jinja2/__init__.py b/instrumentation/opentelemetry-instrumentation-jinja2/src/opentelemetry/instrumentation/jinja2/__init__.py
deleted file mode 100644
index 63f23ae79b4..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/src/opentelemetry/instrumentation/jinja2/__init__.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-
-Usage
------
-
-The OpenTelemetry ``jinja2`` integration traces templates loading, compilation
-and rendering.
-
-Usage
------
-
-.. code-block:: python
-
- from jinja2 import Environment, FileSystemLoader
- from opentelemetry.instrumentation.jinja2 import Jinja2Instrumentor
- from opentelemetry import trace
- from opentelemetry.trace import TracerProvider
-
- trace.set_tracer_provider(TracerProvider())
-
- Jinja2Instrumentor().instrument()
-
- env = Environment(loader=FileSystemLoader("templates"))
- template = env.get_template("mytemplate.html")
-
-API
----
-"""
-# pylint: disable=no-value-for-parameter
-
-import logging
-
-import jinja2
-from wrapt import ObjectProxy
-from wrapt import wrap_function_wrapper as _wrap
-
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.jinja2.version import __version__
-from opentelemetry.instrumentation.utils import unwrap
-from opentelemetry.trace import SpanKind, get_tracer
-from opentelemetry.trace.status import Status, StatusCode
-
-logger = logging.getLogger(__name__)
-
-ATTRIBUTE_JINJA2_TEMPLATE_NAME = "jinja2.template_name"
-ATTRIBUTE_JINJA2_TEMPLATE_PATH = "jinja2.template_path"
-DEFAULT_TEMPLATE_NAME = ""
-
-
-def _with_tracer_wrapper(func):
- """Helper for providing tracer for wrapper functions.
- """
-
- def _with_tracer(tracer):
- def wrapper(wrapped, instance, args, kwargs):
- return func(tracer, wrapped, instance, args, kwargs)
-
- return wrapper
-
- return _with_tracer
-
-
-@_with_tracer_wrapper
-def _wrap_render(tracer, wrapped, instance, args, kwargs):
- """Wrap `Template.render()` or `Template.generate()`
- """
- with tracer.start_as_current_span(
- "jinja2.render", kind=SpanKind.INTERNAL,
- ) as span:
- if span.is_recording():
- template_name = instance.name or DEFAULT_TEMPLATE_NAME
- span.set_attribute(ATTRIBUTE_JINJA2_TEMPLATE_NAME, template_name)
- return wrapped(*args, **kwargs)
-
-
-@_with_tracer_wrapper
-def _wrap_compile(tracer, wrapped, _, args, kwargs):
- with tracer.start_as_current_span(
- "jinja2.compile", kind=SpanKind.INTERNAL,
- ) as span:
- if span.is_recording():
- template_name = (
- args[1]
- if len(args) > 1
- else kwargs.get("name", DEFAULT_TEMPLATE_NAME)
- )
- span.set_attribute(ATTRIBUTE_JINJA2_TEMPLATE_NAME, template_name)
- return wrapped(*args, **kwargs)
-
-
-@_with_tracer_wrapper
-def _wrap_load_template(tracer, wrapped, _, args, kwargs):
- with tracer.start_as_current_span(
- "jinja2.load", kind=SpanKind.INTERNAL,
- ) as span:
- if span.is_recording():
- template_name = kwargs.get("name", args[0])
- span.set_attribute(ATTRIBUTE_JINJA2_TEMPLATE_NAME, template_name)
- template = None
- try:
- template = wrapped(*args, **kwargs)
- return template
- finally:
- if template and span.is_recording():
- span.set_attribute(
- ATTRIBUTE_JINJA2_TEMPLATE_PATH, template.filename
- )
-
-
-class Jinja2Instrumentor(BaseInstrumentor):
- """An instrumentor for jinja2
-
- See `BaseInstrumentor`
- """
-
- def _instrument(self, **kwargs):
- tracer_provider = kwargs.get("tracer_provider")
- tracer = get_tracer(__name__, __version__, tracer_provider)
-
- _wrap(jinja2, "environment.Template.render", _wrap_render(tracer))
- _wrap(jinja2, "environment.Template.generate", _wrap_render(tracer))
- _wrap(jinja2, "environment.Environment.compile", _wrap_compile(tracer))
- _wrap(
- jinja2,
- "environment.Environment._load_template",
- _wrap_load_template(tracer),
- )
-
- def _uninstrument(self, **kwargs):
- unwrap(jinja2.Template, "render")
- unwrap(jinja2.Template, "generate")
- unwrap(jinja2.Environment, "compile")
- unwrap(jinja2.Environment, "_load_template")
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/src/opentelemetry/instrumentation/jinja2/version.py b/instrumentation/opentelemetry-instrumentation-jinja2/src/opentelemetry/instrumentation/jinja2/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/src/opentelemetry/instrumentation/jinja2/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-jinja2/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/tests/templates/base.html b/instrumentation/opentelemetry-instrumentation-jinja2/tests/templates/base.html
deleted file mode 100644
index 05490d0c021..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/tests/templates/base.html
+++ /dev/null
@@ -1 +0,0 @@
-Message: {% block content %}{% endblock %}
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/tests/templates/template.html b/instrumentation/opentelemetry-instrumentation-jinja2/tests/templates/template.html
deleted file mode 100644
index ab281824151..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/tests/templates/template.html
+++ /dev/null
@@ -1,2 +0,0 @@
-{% extends 'base.html' %}
-{% block content %}Hello {{name}}!{% endblock %}
diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/tests/test_jinja2.py b/instrumentation/opentelemetry-instrumentation-jinja2/tests/test_jinja2.py
deleted file mode 100644
index 5de1d598cbc..00000000000
--- a/instrumentation/opentelemetry-instrumentation-jinja2/tests/test_jinja2.py
+++ /dev/null
@@ -1,210 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-from unittest import mock
-
-import jinja2
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.jinja2 import Jinja2Instrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace import get_tracer
-
-TEST_DIR = os.path.dirname(os.path.realpath(__file__))
-TMPL_DIR = os.path.join(TEST_DIR, "templates")
-
-
-class TestJinja2Instrumentor(TestBase):
- def setUp(self):
- super().setUp()
- Jinja2Instrumentor().instrument()
- # prevent cache effects when using Template('code...')
- # pylint: disable=protected-access
- jinja2.environment._spontaneous_environments.clear()
- self.tracer = get_tracer(__name__)
-
- def tearDown(self):
- super().tearDown()
- Jinja2Instrumentor().uninstrument()
-
- def test_render_inline_template_with_root(self):
- with self.tracer.start_as_current_span("root"):
- template = jinja2.environment.Template("Hello {{name}}!")
- self.assertEqual(template.render(name="Jinja"), "Hello Jinja!")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 3)
-
- # pylint:disable=unbalanced-tuple-unpacking
- render, template, root = spans[:3]
-
- self.assertIs(render.parent, root.get_span_context())
- self.assertIs(template.parent, root.get_span_context())
- self.assertIsNone(root.parent)
-
- def test_render_not_recording(self):
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = mock_span
- with mock.patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- jinja2.environment.Template("Hello {{name}}!")
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_render_inline_template(self):
- template = jinja2.environment.Template("Hello {{name}}!")
- self.assertEqual(template.render(name="Jinja"), "Hello Jinja!")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
-
- # pylint:disable=unbalanced-tuple-unpacking
- template, render = spans
-
- self.assertEqual(template.name, "jinja2.compile")
- self.assertIs(template.kind, trace_api.SpanKind.INTERNAL)
- self.assertEqual(
- template.attributes, {"jinja2.template_name": ""},
- )
-
- self.assertEqual(render.name, "jinja2.render")
- self.assertIs(render.kind, trace_api.SpanKind.INTERNAL)
- self.assertEqual(
- render.attributes, {"jinja2.template_name": ""},
- )
-
- def test_generate_inline_template_with_root(self):
- with self.tracer.start_as_current_span("root"):
- template = jinja2.environment.Template("Hello {{name}}!")
- self.assertEqual(
- "".join(template.generate(name="Jinja")), "Hello Jinja!"
- )
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 3)
-
- # pylint:disable=unbalanced-tuple-unpacking
- template, generate, root = spans
-
- self.assertIs(generate.parent, root.get_span_context())
- self.assertIs(template.parent, root.get_span_context())
- self.assertIsNone(root.parent)
-
- def test_generate_inline_template(self):
- template = jinja2.environment.Template("Hello {{name}}!")
- self.assertEqual(
- "".join(template.generate(name="Jinja")), "Hello Jinja!"
- )
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
-
- # pylint:disable=unbalanced-tuple-unpacking
- template, generate = spans[:2]
-
- self.assertEqual(template.name, "jinja2.compile")
- self.assertIs(template.kind, trace_api.SpanKind.INTERNAL)
- self.assertEqual(
- template.attributes, {"jinja2.template_name": ""},
- )
-
- self.assertEqual(generate.name, "jinja2.render")
- self.assertIs(generate.kind, trace_api.SpanKind.INTERNAL)
- self.assertEqual(
- generate.attributes, {"jinja2.template_name": ""},
- )
-
- def test_file_template_with_root(self):
- with self.tracer.start_as_current_span("root"):
- loader = jinja2.loaders.FileSystemLoader(TMPL_DIR)
- env = jinja2.Environment(loader=loader)
- template = env.get_template("template.html")
- self.assertEqual(
- template.render(name="Jinja"), "Message: Hello Jinja!"
- )
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 6)
-
- # pylint:disable=unbalanced-tuple-unpacking
- compile2, load2, compile1, load1, render, root = spans
-
- self.assertIs(compile2.parent, load2.get_span_context())
- self.assertIs(load2.parent, root.get_span_context())
- self.assertIs(compile1.parent, load1.get_span_context())
- self.assertIs(load1.parent, render.get_span_context())
- self.assertIs(render.parent, root.get_span_context())
- self.assertIsNone(root.parent)
-
- def test_file_template(self):
- loader = jinja2.loaders.FileSystemLoader(TMPL_DIR)
- env = jinja2.Environment(loader=loader)
- template = env.get_template("template.html")
- self.assertEqual(
- template.render(name="Jinja"), "Message: Hello Jinja!"
- )
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 5)
-
- # pylint:disable=unbalanced-tuple-unpacking
- compile2, load2, compile1, load1, render = spans
-
- self.assertEqual(compile2.name, "jinja2.compile")
- self.assertEqual(load2.name, "jinja2.load")
- self.assertEqual(compile1.name, "jinja2.compile")
- self.assertEqual(load1.name, "jinja2.load")
- self.assertEqual(render.name, "jinja2.render")
-
- self.assertEqual(
- compile2.attributes, {"jinja2.template_name": "template.html"},
- )
- self.assertEqual(
- load2.attributes,
- {
- "jinja2.template_name": "template.html",
- "jinja2.template_path": os.path.join(
- TMPL_DIR, "template.html"
- ),
- },
- )
- self.assertEqual(
- compile1.attributes, {"jinja2.template_name": "base.html"},
- )
- self.assertEqual(
- load1.attributes,
- {
- "jinja2.template_name": "base.html",
- "jinja2.template_path": os.path.join(TMPL_DIR, "base.html"),
- },
- )
- self.assertEqual(
- render.attributes, {"jinja2.template_name": "template.html"},
- )
-
- def test_uninstrumented(self):
- Jinja2Instrumentor().uninstrument()
-
- jinja2.environment.Template("Hello {{name}}!")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 0)
-
- Jinja2Instrumentor().instrument()
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-mysql/CHANGELOG.md
deleted file mode 100644
index 83563772122..00000000000
--- a/instrumentation/opentelemetry-instrumentation-mysql/CHANGELOG.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-mysql
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## Version 0.11b0
-
-Released 2020-07-28
-
-- bugfix: Fix auto-instrumentation entry point for mysql
- ([#858](https://github.com/open-telemetry/opentelemetry-python/pull/858))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Implement instrumentor interface ([#654](https://github.com/open-telemetry/opentelemetry-python/pull/654))
-
-## 0.4a0
-
-Released 2020-02-21
-
-- Initial release
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/LICENSE b/instrumentation/opentelemetry-instrumentation-mysql/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-mysql/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-mysql/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-mysql/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-mysql/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/README.rst b/instrumentation/opentelemetry-instrumentation-mysql/README.rst
deleted file mode 100644
index 9558f64bd9b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-mysql/README.rst
+++ /dev/null
@@ -1,25 +0,0 @@
-OpenTelemetry MySQL Instrumentation
-===================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-mysql.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-mysql/
-
-Instrumentation with MySQL that supports the mysql-connector library and is
-specified to trace_integration using 'MySQL'.
-
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-mysql
-
-
-References
-----------
-* `OpenTelemetry MySQL Instrumentation `_
-* `OpenTelemetry Project `_
-
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/setup.cfg b/instrumentation/opentelemetry-instrumentation-mysql/setup.cfg
deleted file mode 100644
index ff9984a0c57..00000000000
--- a/instrumentation/opentelemetry-instrumentation-mysql/setup.cfg
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-mysql
-description = OpenTelemetry MySQL instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-mysql
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation-dbapi == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- mysql-connector-python ~= 8.0
- wrapt >= 1.0.0, < 2.0.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- mysql = opentelemetry.instrumentation.mysql:MySQLInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/setup.py b/instrumentation/opentelemetry-instrumentation-mysql/setup.py
deleted file mode 100644
index 955f75d71e0..00000000000
--- a/instrumentation/opentelemetry-instrumentation-mysql/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "mysql", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py
deleted file mode 100644
index 1cbd240cc59..00000000000
--- a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-MySQL instrumentation supporting `mysql-connector`_, it can be enabled by
-using ``MySQLInstrumentor``.
-
-.. _mysql-connector: https://pypi.org/project/mysql-connector/
-
-Usage
------
-
-.. code:: python
-
- import mysql.connector
- from opentelemetry import trace
- from opentelemetry.trace import TracerProvider
- from opentelemetry.instrumentation.mysql import MySQLInstrumentor
-
- trace.set_tracer_provider(TracerProvider())
-
- MySQLInstrumentor().instrument()
-
- cnx = mysql.connector.connect(database="MySQL_Database")
- cursor = cnx.cursor()
- cursor.execute("INSERT INTO test (testField) VALUES (123)"
- cursor.close()
- cnx.close()
-
-API
----
-"""
-
-import mysql.connector
-
-from opentelemetry.instrumentation import dbapi
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.mysql.version import __version__
-from opentelemetry.trace import get_tracer
-
-
-class MySQLInstrumentor(BaseInstrumentor):
- _CONNECTION_ATTRIBUTES = {
- "database": "database",
- "port": "server_port",
- "host": "server_host",
- "user": "user",
- }
-
- _DATABASE_COMPONENT = "mysql"
- _DATABASE_TYPE = "sql"
-
- def _instrument(self, **kwargs):
- """Integrate with MySQL Connector/Python library.
- https://dev.mysql.com/doc/connector-python/en/
- """
- tracer_provider = kwargs.get("tracer_provider")
-
- dbapi.wrap_connect(
- __name__,
- mysql.connector,
- "connect",
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- version=__version__,
- tracer_provider=tracer_provider,
- )
-
- def _uninstrument(self, **kwargs):
- """"Disable MySQL instrumentation"""
- dbapi.unwrap_connect(mysql.connector, "connect")
-
- # pylint:disable=no-self-use
- def instrument_connection(self, connection):
- """Enable instrumentation in a MySQL connection.
-
- Args:
- connection: The connection to instrument.
-
- Returns:
- An instrumented connection.
- """
- tracer = get_tracer(__name__, __version__)
-
- return dbapi.instrument_connection(
- tracer,
- connection,
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- )
-
- def uninstrument_connection(self, connection):
- """Disable instrumentation in a MySQL connection.
-
- Args:
- connection: The connection to uninstrument.
-
- Returns:
- An uninstrumented connection.
- """
- return dbapi.uninstrument_connection(connection)
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/version.py b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-mysql/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py b/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py
deleted file mode 100644
index 6c114d969f0..00000000000
--- a/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest import mock
-
-import mysql.connector
-
-import opentelemetry.instrumentation.mysql
-from opentelemetry.instrumentation.mysql import MySQLInstrumentor
-from opentelemetry.sdk import resources
-from opentelemetry.test.test_base import TestBase
-
-
-class TestMysqlIntegration(TestBase):
- def tearDown(self):
- super().tearDown()
- with self.disable_logging():
- MySQLInstrumentor().uninstrument()
-
- @mock.patch("mysql.connector.connect")
- # pylint: disable=unused-argument
- def test_instrumentor(self, mock_connect):
- MySQLInstrumentor().instrument()
-
- cnx = mysql.connector.connect(database="test")
- cursor = cnx.cursor()
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.mysql
- )
-
- # check that no spans are generated after uninstrumen
- MySQLInstrumentor().uninstrument()
-
- cnx = mysql.connector.connect(database="test")
- cursor = cnx.cursor()
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- @mock.patch("mysql.connector.connect")
- # pylint: disable=unused-argument
- def test_custom_tracer_provider(self, mock_connect):
- resource = resources.Resource.create({})
- result = self.create_tracer_provider(resource=resource)
- tracer_provider, exporter = result
-
- MySQLInstrumentor().instrument(tracer_provider=tracer_provider)
- cnx = mysql.connector.connect(database="test")
- cursor = cnx.cursor()
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- span_list = exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
- span = span_list[0]
-
- self.assertIs(span.resource, resource)
-
- @mock.patch("mysql.connector.connect")
- # pylint: disable=unused-argument
- def test_instrument_connection(self, mock_connect):
- cnx = mysql.connector.connect(database="test")
- query = "SELECT * FROM test"
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 0)
-
- cnx = MySQLInstrumentor().instrument_connection(cnx)
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- @mock.patch("mysql.connector.connect")
- # pylint: disable=unused-argument
- def test_uninstrument_connection(self, mock_connect):
- MySQLInstrumentor().instrument()
- cnx = mysql.connector.connect(database="test")
- query = "SELECT * FROM test"
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- cnx = MySQLInstrumentor().uninstrument_connection(cnx)
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-opentracing-shim/CHANGELOG.md
deleted file mode 100644
index be243d95847..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/CHANGELOG.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change reference names to opentelemetry-instrumentation-opentracing-shim
- ([#969](https://github.com/open-telemetry/opentelemetry-python/pull/969))
-
-## 0.3a0
-
-Released 2019-12-11
-
-- Implement extract and inject support for HTTP_HEADERS and TEXT_MAP formats
- ([#256](https://github.com/open-telemetry/opentelemetry-python/pull/256))
-
-## 0.2a0
-
-Released 2019-10-29
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/LICENSE b/instrumentation/opentelemetry-instrumentation-opentracing-shim/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-opentracing-shim/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-opentracing-shim/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/README.rst
deleted file mode 100644
index 7a8413ef59d..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/README.rst
+++ /dev/null
@@ -1,20 +0,0 @@
-OpenTracing Shim for OpenTelemetry
-==================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-opentracing-shim.svg
- :target: https://pypi.org/project/opentelemetry-opentracing-shim/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-opentracing-shim
-
-References
-----------
-
-* `OpenTracing Shim for OpenTelemetry `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/setup.cfg b/instrumentation/opentelemetry-instrumentation-opentracing-shim/setup.cfg
deleted file mode 100644
index 33cad7b9351..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/setup.cfg
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-opentracing-shim
-description = OpenTracing Shim for OpenTelemetry
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-opentracing-shim
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- Deprecated >= 1.2.6
- opentracing ~= 2.0
- opentelemetry-api == 0.16.dev0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
- opentracing ~= 2.2.0
-
-[options.packages.find]
-where = src
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/setup.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/setup.py
deleted file mode 100644
index f5d71a86b56..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "opentracing_shim",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/__init__.py
deleted file mode 100644
index 00a0b8d0cb8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/__init__.py
+++ /dev/null
@@ -1,723 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-The OpenTelemetry OpenTracing shim is a library which allows an easy migration
-from OpenTracing to OpenTelemetry.
-
-The shim consists of a set of classes which implement the OpenTracing Python
-API while using OpenTelemetry constructs behind the scenes. Its purpose is to
-allow applications which are already instrumented using OpenTracing to start
-using OpenTelemetry with a minimal effort, without having to rewrite large
-portions of the codebase.
-
-To use the shim, a :class:`TracerShim` instance is created and then used as if
-it were an "ordinary" OpenTracing :class:`opentracing.Tracer`, as in the
-following example::
-
- import time
-
- from opentelemetry import trace
- from opentelemetry.sdk.trace import TracerProvider
- from opentelemetry.instrumentation.opentracing_shim import create_tracer
-
- # Define which OpenTelemetry Tracer provider implementation to use.
- trace.set_tracer_provider(TracerProvider())
-
- # Create an OpenTelemetry Tracer.
- otel_tracer = trace.get_tracer(__name__)
-
- # Create an OpenTracing shim.
- shim = create_tracer(otel_tracer)
-
- with shim.start_active_span("ProcessHTTPRequest"):
- print("Processing HTTP request")
- # Sleeping to mock real work.
- time.sleep(0.1)
- with shim.start_active_span("GetDataFromDB"):
- print("Getting data from DB")
- # Sleeping to mock real work.
- time.sleep(0.2)
-
-Note:
- While the OpenTracing Python API represents time values as the number of
- **seconds** since the epoch expressed as :obj:`float` values, the
- OpenTelemetry Python API represents time values as the number of
- **nanoseconds** since the epoch expressed as :obj:`int` values. This fact
- requires the OpenTracing shim to convert time values back and forth between
- the two representations, which involves floating point arithmetic.
-
- Due to the way computers represent floating point values in hardware,
- representation of decimal floating point values in binary-based hardware is
- imprecise by definition.
-
- The above results in **slight imprecisions** in time values passed to the
- shim via the OpenTracing API when comparing the value passed to the shim
- and the value stored in the OpenTelemetry :class:`opentelemetry.trace.Span`
- object behind the scenes. **This is not a bug in this library or in
- Python**. Rather, this is a generic problem which stems from the fact that
- not every decimal floating point number can be correctly represented in
- binary, and therefore affects other libraries and programming languages as
- well. More information about this problem can be found in the
- `Floating Point Arithmetic\\: Issues and Limitations`_ section of the
- Python documentation.
-
- While testing this library, the aforementioned imprecisions were observed
- to be of *less than a microsecond*.
-
-API
----
-.. _Floating Point Arithmetic\\: Issues and Limitations:
- https://docs.python.org/3/tutorial/floatingpoint.html
-"""
-
-# TODO: make pylint use 3p opentracing module for type inference
-# pylint:disable=no-member
-
-import logging
-from typing import Optional, TypeVar, Union
-
-from deprecated import deprecated
-from opentracing import (
- Format,
- Scope,
- ScopeManager,
- Span,
- SpanContext,
- Tracer,
- UnsupportedFormatException,
-)
-
-from opentelemetry import propagators
-from opentelemetry.baggage import get_baggage, set_baggage
-from opentelemetry.context import Context, attach, detach, get_value, set_value
-from opentelemetry.instrumentation.opentracing_shim import util
-from opentelemetry.instrumentation.opentracing_shim.version import __version__
-from opentelemetry.trace import INVALID_SPAN_CONTEXT, DefaultSpan, Link
-from opentelemetry.trace import SpanContext as OtelSpanContext
-from opentelemetry.trace import Tracer as OtelTracer
-from opentelemetry.trace import (
- TracerProvider,
- get_current_span,
- set_span_in_context,
-)
-from opentelemetry.trace.propagation.textmap import DictGetter
-from opentelemetry.util.types import Attributes
-
-ValueT = TypeVar("ValueT", int, float, bool, str)
-logger = logging.getLogger(__name__)
-
-
-def create_tracer(otel_tracer_provider: TracerProvider) -> "TracerShim":
- """Creates a :class:`TracerShim` object from the provided OpenTelemetry
- :class:`opentelemetry.trace.TracerProvider`.
-
- The returned :class:`TracerShim` is an implementation of
- :class:`opentracing.Tracer` using OpenTelemetry under the hood.
-
- Args:
- otel_tracer_provider: A tracer from this provider will be used to
- perform the actual tracing when user code is instrumented using the
- OpenTracing API.
-
- Returns:
- The created :class:`TracerShim`.
- """
-
- return TracerShim(otel_tracer_provider.get_tracer(__name__, __version__))
-
-
-class SpanContextShim(SpanContext):
- """Implements :class:`opentracing.SpanContext` by wrapping a
- :class:`opentelemetry.trace.SpanContext` object.
-
- Args:
- otel_context: A :class:`opentelemetry.trace.SpanContext` to be used for
- constructing the :class:`SpanContextShim`.
- """
-
- def __init__(self, otel_context: OtelSpanContext):
- self._otel_context = otel_context
- # Context is being used here since it must be immutable.
- self._baggage = Context()
-
- def unwrap(self) -> OtelSpanContext:
- """Returns the wrapped :class:`opentelemetry.trace.SpanContext`
- object.
-
- Returns:
- The :class:`opentelemetry.trace.SpanContext` object wrapped by this
- :class:`SpanContextShim`.
- """
-
- return self._otel_context
-
- @property
- def baggage(self) -> Context:
- """Returns the ``baggage`` associated with this object"""
-
- return self._baggage
-
-
-class SpanShim(Span):
- """Wraps a :class:`opentelemetry.trace.Span` object.
-
- Args:
- tracer: The :class:`opentracing.Tracer` that created this `SpanShim`.
- context: A :class:`SpanContextShim` which contains the context for this
- :class:`SpanShim`.
- span: A :class:`opentelemetry.trace.Span` to wrap.
- """
-
- def __init__(self, tracer, context: SpanContextShim, span):
- super().__init__(tracer, context)
- self._otel_span = span
-
- def unwrap(self):
- """Returns the wrapped :class:`opentelemetry.trace.Span` object.
-
- Returns:
- The :class:`opentelemetry.trace.Span` object wrapped by this
- :class:`SpanShim`.
- """
-
- return self._otel_span
-
- def set_operation_name(self, operation_name: str) -> "SpanShim":
- """Updates the name of the wrapped OpenTelemetry span.
-
- Args:
- operation_name: The new name to be used for the underlying
- :class:`opentelemetry.trace.Span` object.
-
- Returns:
- Returns this :class:`SpanShim` instance to allow call chaining.
- """
-
- self._otel_span.update_name(operation_name)
- return self
-
- def finish(self, finish_time: float = None):
- """Ends the OpenTelemetry span wrapped by this :class:`SpanShim`.
-
- If *finish_time* is provided, the time value is converted to the
- OpenTelemetry time format (number of nanoseconds since the epoch,
- expressed as an integer) and passed on to the OpenTelemetry tracer when
- ending the OpenTelemetry span. If *finish_time* isn't provided, it is
- up to the OpenTelemetry tracer implementation to generate a timestamp
- when ending the span.
-
- Args:
- finish_time: A value that represents the finish time expressed as
- the number of seconds since the epoch as returned by
- :func:`time.time()`.
- """
-
- end_time = finish_time
- if end_time is not None:
- end_time = util.time_seconds_to_ns(finish_time)
- self._otel_span.end(end_time=end_time)
-
- def set_tag(self, key: str, value: ValueT) -> "SpanShim":
- """Sets an OpenTelemetry attribute on the wrapped OpenTelemetry span.
-
- Args:
- key: A tag key.
- value: A tag value.
-
- Returns:
- Returns this :class:`SpanShim` instance to allow call chaining.
- """
-
- self._otel_span.set_attribute(key, value)
- return self
-
- def log_kv(
- self, key_values: Attributes, timestamp: float = None
- ) -> "SpanShim":
- """Logs an event for the wrapped OpenTelemetry span.
-
- Note:
- The OpenTracing API defines the values of *key_values* to be of any
- type. However, the OpenTelemetry API requires that the values be
- any one of the types defined in
- ``opentelemetry.trace.util.Attributes`` therefore, only these types
- are supported as values.
-
- Args:
- key_values: A dictionary as specified in
- ``opentelemetry.trace.util.Attributes``.
- timestamp: Timestamp of the OpenTelemetry event, will be generated
- automatically if omitted.
-
- Returns:
- Returns this :class:`SpanShim` instance to allow call chaining.
- """
-
- if timestamp is not None:
- event_timestamp = util.time_seconds_to_ns(timestamp)
- else:
- event_timestamp = None
-
- event_name = util.event_name_from_kv(key_values)
- self._otel_span.add_event(event_name, key_values, event_timestamp)
- return self
-
- @deprecated(reason="This method is deprecated in favor of log_kv")
- def log(self, **kwargs):
- super().log(**kwargs)
-
- @deprecated(reason="This method is deprecated in favor of log_kv")
- def log_event(self, event, payload=None):
- super().log_event(event, payload=payload)
-
- def set_baggage_item(self, key: str, value: str):
- """Stores a Baggage item in the span as a key/value
- pair.
-
- Args:
- key: A tag key.
- value: A tag value.
- """
- # pylint: disable=protected-access
- self._context._baggage = set_baggage(
- key, value, context=self._context._baggage
- )
-
- def get_baggage_item(self, key: str) -> Optional[object]:
- """Retrieves value of the baggage item with the given key.
-
- Args:
- key: A tag key.
- Returns:
- Returns this :class:`SpanShim` instance to allow call chaining.
- """
- # pylint: disable=protected-access
- return get_baggage(key, context=self._context._baggage)
-
-
-class ScopeShim(Scope):
- """A `ScopeShim` wraps the OpenTelemetry functionality related to span
- activation/deactivation while using OpenTracing :class:`opentracing.Scope`
- objects for presentation.
-
- Unlike other classes in this package, the `ScopeShim` class doesn't wrap an
- OpenTelemetry class because OpenTelemetry doesn't have the notion of
- "scope" (though it *does* have similar functionality).
-
- There are two ways to construct a `ScopeShim` object: using the default
- initializer and using the :meth:`from_context_manager()` class method.
-
- It is necessary to have both ways for constructing `ScopeShim` objects
- because in some cases we need to create the object from an OpenTelemetry
- `opentelemetry.trace.Span` context manager (as returned by
- :meth:`opentelemetry.trace.Tracer.use_span`), in which case our only way of
- retrieving a `opentelemetry.trace.Span` object is by calling the
- ``__enter__()`` method on the context manager, which makes the span active
- in the OpenTelemetry tracer; whereas in other cases we need to accept a
- `SpanShim` object and wrap it in a `ScopeShim`. The former is used mainly
- when the instrumentation code retrieves the currently-active span using
- `ScopeManagerShim.active`. The latter is mainly used when the
- instrumentation code activates a span using
- :meth:`ScopeManagerShim.activate`.
-
- Args:
- manager: The :class:`ScopeManagerShim` that created this
- :class:`ScopeShim`.
- span: The :class:`SpanShim` this :class:`ScopeShim` controls.
- span_cm: A Python context manager which yields an OpenTelemetry
- `opentelemetry.trace.Span` from its ``__enter__()`` method. Used
- by :meth:`from_context_manager` to store the context manager as
- an attribute so that it can later be closed by calling its
- ``__exit__()`` method. Defaults to `None`.
- """
-
- def __init__(
- self, manager: "ScopeManagerShim", span: SpanShim, span_cm=None
- ):
- super().__init__(manager, span)
- self._span_cm = span_cm
- self._token = attach(set_value("scope_shim", self))
-
- # TODO: Change type of `manager` argument to `opentracing.ScopeManager`? We
- # need to get rid of `manager.tracer` for this.
- @classmethod
- def from_context_manager(cls, manager: "ScopeManagerShim", span_cm):
- """Constructs a :class:`ScopeShim` from an OpenTelemetry
- `opentelemetry.trace.Span` context
- manager.
-
- The method extracts a `opentelemetry.trace.Span` object from the
- context manager by calling the context manager's ``__enter__()``
- method. This causes the span to start in the OpenTelemetry tracer.
-
- Example usage::
-
- span = otel_tracer.start_span("TestSpan")
- span_cm = otel_tracer.use_span(span)
- scope_shim = ScopeShim.from_context_manager(
- scope_manager_shim,
- span_cm=span_cm,
- )
-
- Args:
- manager: The :class:`ScopeManagerShim` that created this
- :class:`ScopeShim`.
- span_cm: A context manager as returned by
- :meth:`opentelemetry.trace.Tracer.use_span`.
- """
-
- otel_span = span_cm.__enter__()
- span_context = SpanContextShim(otel_span.get_span_context())
- span = SpanShim(manager.tracer, span_context, otel_span)
- return cls(manager, span, span_cm)
-
- def close(self):
- """Closes the `ScopeShim`. If the `ScopeShim` was created from a
- context manager, calling this method sets the active span in the
- OpenTelemetry tracer back to the span which was active before this
- `ScopeShim` was created. In addition, if the span represented by this
- `ScopeShim` was activated with the *finish_on_close* argument set to
- `True`, calling this method will end the span.
-
- Warning:
- In the current state of the implementation it is possible to create
- a `ScopeShim` directly from a `SpanShim`, that is - without using
- :meth:`from_context_manager()`. For that reason we need to be able
- to end the span represented by the `ScopeShim` in this case, too.
- Please note that closing a `ScopeShim` created this way (for
- example as returned by :meth:`ScopeManagerShim.active`) **always
- ends the associated span**, regardless of the value passed in
- *finish_on_close* when activating the span.
- """
-
- detach(self._token)
-
- if self._span_cm is not None:
- # We don't have error information to pass to `__exit__()` so we
- # pass `None` in all arguments. If the OpenTelemetry tracer
- # implementation requires this information, the `__exit__()` method
- # on `opentracing.Scope` should be overridden and modified to pass
- # the relevant values to this `close()` method.
- self._span_cm.__exit__(None, None, None)
- else:
- self._span.unwrap().end()
-
-
-class ScopeManagerShim(ScopeManager):
- """Implements :class:`opentracing.ScopeManager` by setting and getting the
- active `opentelemetry.trace.Span` in the OpenTelemetry tracer.
-
- This class keeps a reference to a :class:`TracerShim` as an attribute. This
- reference is used to communicate with the OpenTelemetry tracer. It is
- necessary to have a reference to the :class:`TracerShim` rather than the
- :class:`opentelemetry.trace.Tracer` wrapped by it because when constructing
- a :class:`SpanShim` we need to pass a reference to a
- :class:`opentracing.Tracer`.
-
- Args:
- tracer: A :class:`TracerShim` to use for setting and getting active
- span state.
- """
-
- def __init__(self, tracer: "TracerShim"):
- # The only thing the ``__init__()``` method on the base class does is
- # initialize `self._noop_span` and `self._noop_scope` with no-op
- # objects. Therefore, it doesn't seem useful to call it.
- # pylint: disable=super-init-not-called
- self._tracer = tracer
-
- def activate(self, span: SpanShim, finish_on_close: bool) -> "ScopeShim":
- """Activates a :class:`SpanShim` and returns a :class:`ScopeShim` which
- represents the active span.
-
- Args:
- span: A :class:`SpanShim` to be activated.
- finish_on_close(:obj:`bool`): Determines whether the OpenTelemetry
- span should be ended when the returned :class:`ScopeShim` is
- closed.
-
- Returns:
- A :class:`ScopeShim` representing the activated span.
- """
-
- span_cm = self._tracer.unwrap().use_span(
- span.unwrap(), end_on_exit=finish_on_close
- )
- return ScopeShim.from_context_manager(self, span_cm=span_cm)
-
- @property
- def active(self) -> "ScopeShim":
- """Returns a :class:`ScopeShim` object representing the
- currently-active span in the OpenTelemetry tracer.
-
- Returns:
- A :class:`ScopeShim` representing the active span in the
- OpenTelemetry tracer, or `None` if no span is currently active.
-
- Warning:
- Calling :meth:`ScopeShim.close` on the :class:`ScopeShim` returned
- by this property **always ends the corresponding span**, regardless
- of the *finish_on_close* value used when activating the span. This
- is a limitation of the current implementation of the OpenTracing
- shim and is likely to be handled in future versions.
- """
-
- span = get_current_span()
- if span.get_span_context() == INVALID_SPAN_CONTEXT:
- return None
-
- try:
- return get_value("scope_shim")
- except KeyError:
- span_context = SpanContextShim(span.get_span_context())
- wrapped_span = SpanShim(self._tracer, span_context, span)
- return ScopeShim(self, span=wrapped_span)
-
- @property
- def tracer(self) -> "TracerShim":
- """Returns the :class:`TracerShim` reference used by this
- :class:`ScopeManagerShim` for setting and getting the active span from
- the OpenTelemetry tracer.
-
- Returns:
- The :class:`TracerShim` used for setting and getting the active
- span.
-
- Warning:
- This property is *not* a part of the OpenTracing API. It used
- internally by the current implementation of the OpenTracing shim
- and will likely be removed in future versions.
- """
-
- return self._tracer
-
-
-class TracerShim(Tracer):
- """Wraps a :class:`opentelemetry.trace.Tracer` object.
-
- This wrapper class allows using an OpenTelemetry tracer as if it were an
- OpenTracing tracer. It exposes the same methods as an "ordinary"
- OpenTracing tracer, and uses OpenTelemetry transparently for performing the
- actual tracing.
-
- This class depends on the *OpenTelemetry API*. Therefore, any
- implementation of a :class:`opentelemetry.trace.Tracer` should work with
- this class.
-
- Args:
- tracer: A :class:`opentelemetry.trace.Tracer` to use for tracing. This
- tracer will be invoked by the shim to create actual spans.
- """
-
- def __init__(self, tracer: OtelTracer):
- super().__init__(scope_manager=ScopeManagerShim(self))
- self._otel_tracer = tracer
- self._supported_formats = (
- Format.TEXT_MAP,
- Format.HTTP_HEADERS,
- )
- self._carrier_getter = DictGetter()
-
- def unwrap(self):
- """Returns the :class:`opentelemetry.trace.Tracer` object that is
- wrapped by this :class:`TracerShim` and used for actual tracing.
-
- Returns:
- The :class:`opentelemetry.trace.Tracer` used for actual tracing.
- """
-
- return self._otel_tracer
-
- def start_active_span(
- self,
- operation_name: str,
- child_of: Union[SpanShim, SpanContextShim] = None,
- references: list = None,
- tags: Attributes = None,
- start_time: float = None,
- ignore_active_span: bool = False,
- finish_on_close: bool = True,
- ) -> "ScopeShim":
- """Starts and activates a span. In terms of functionality, this method
- behaves exactly like the same method on a "regular" OpenTracing tracer.
- See :meth:`opentracing.Tracer.start_active_span` for more details.
-
- Args:
- operation_name: Name of the operation represented by
- the new span from the perspective of the current service.
- child_of: A :class:`SpanShim` or :class:`SpanContextShim`
- representing the parent in a "child of" reference. If
- specified, the *references* parameter must be omitted.
- references: A list of :class:`opentracing.Reference` objects that
- identify one or more parents of type :class:`SpanContextShim`.
- tags: A dictionary of tags.
- start_time: An explicit start time expressed as the number of
- seconds since the epoch as returned by :func:`time.time()`.
- ignore_active_span: Ignore the currently-active span in the
- OpenTelemetry tracer and make the created span the root span of
- a new trace.
- finish_on_close: Determines whether the created span should end
- automatically when closing the returned :class:`ScopeShim`.
-
- Returns:
- A :class:`ScopeShim` that is already activated by the
- :class:`ScopeManagerShim`.
- """
-
- current_span = get_current_span()
-
- if child_of is None and current_span is not INVALID_SPAN_CONTEXT:
- child_of = SpanShim(None, None, current_span)
-
- span = self.start_span(
- operation_name=operation_name,
- child_of=child_of,
- references=references,
- tags=tags,
- start_time=start_time,
- ignore_active_span=ignore_active_span,
- )
- return self._scope_manager.activate(span, finish_on_close)
-
- def start_span(
- self,
- operation_name: str = None,
- child_of: Union[SpanShim, SpanContextShim] = None,
- references: list = None,
- tags: Attributes = None,
- start_time: float = None,
- ignore_active_span: bool = False,
- ) -> SpanShim:
- """Implements the ``start_span()`` method from the base class.
-
- Starts a span. In terms of functionality, this method behaves exactly
- like the same method on a "regular" OpenTracing tracer. See
- :meth:`opentracing.Tracer.start_span` for more details.
-
- Args:
- operation_name: Name of the operation represented by the new span
- from the perspective of the current service.
- child_of: A :class:`SpanShim` or :class:`SpanContextShim`
- representing the parent in a "child of" reference. If
- specified, the *references* parameter must be omitted.
- references: A list of :class:`opentracing.Reference` objects that
- identify one or more parents of type :class:`SpanContextShim`.
- tags: A dictionary of tags.
- start_time: An explicit start time expressed as the number of
- seconds since the epoch as returned by :func:`time.time()`.
- ignore_active_span: Ignore the currently-active span in the
- OpenTelemetry tracer and make the created span the root span of
- a new trace.
-
- Returns:
- An already-started :class:`SpanShim` instance.
- """
-
- # Use active span as parent when no explicit parent is specified.
- if not ignore_active_span and not child_of:
- child_of = self.active_span
-
- # Use the specified parent or the active span if possible. Otherwise,
- # use a `None` parent, which triggers the creation of a new trace.
- parent = child_of.unwrap() if child_of else None
- if isinstance(parent, OtelSpanContext):
- parent = DefaultSpan(parent)
-
- parent_span_context = set_span_in_context(parent)
-
- links = []
- if references:
- for ref in references:
- links.append(Link(ref.referenced_context.unwrap()))
-
- # The OpenTracing API expects time values to be `float` values which
- # represent the number of seconds since the epoch. OpenTelemetry
- # represents time values as nanoseconds since the epoch.
- start_time_ns = start_time
- if start_time_ns is not None:
- start_time_ns = util.time_seconds_to_ns(start_time)
-
- span = self._otel_tracer.start_span(
- operation_name,
- context=parent_span_context,
- links=links,
- attributes=tags,
- start_time=start_time_ns,
- )
-
- context = SpanContextShim(span.get_span_context())
- return SpanShim(self, context, span)
-
- def inject(self, span_context, format: object, carrier: object):
- """Injects ``span_context`` into ``carrier``.
-
- See base class for more details.
-
- Args:
- span_context: The ``opentracing.SpanContext`` to inject.
- format: a Python object instance that represents a given
- carrier format. `format` may be of any type, and `format`
- equality is defined by Python ``==`` operator.
- carrier: the format-specific carrier object to inject into
- """
-
- # pylint: disable=redefined-builtin
- # This implementation does not perform the injecting by itself but
- # uses the configured propagators in opentelemetry.propagators.
- # TODO: Support Format.BINARY once it is supported in
- # opentelemetry-python.
-
- if format not in self._supported_formats:
- raise UnsupportedFormatException
-
- propagator = propagators.get_global_textmap()
-
- ctx = set_span_in_context(DefaultSpan(span_context.unwrap()))
- propagator.inject(type(carrier).__setitem__, carrier, context=ctx)
-
- def extract(self, format: object, carrier: object):
- """Returns an ``opentracing.SpanContext`` instance extracted from a
- ``carrier``.
-
- See base class for more details.
-
- Args:
- format: a Python object instance that represents a given
- carrier format. ``format`` may be of any type, and ``format``
- equality is defined by python ``==`` operator.
- carrier: the format-specific carrier object to extract from
-
- Returns:
- An ``opentracing.SpanContext`` extracted from ``carrier`` or
- ``None`` if no such ``SpanContext`` could be found.
- """
-
- # pylint: disable=redefined-builtin
- # This implementation does not perform the extracing by itself but
- # uses the configured propagators in opentelemetry.propagators.
- # TODO: Support Format.BINARY once it is supported in
- # opentelemetry-python.
- if format not in self._supported_formats:
- raise UnsupportedFormatException
-
- propagator = propagators.get_global_textmap()
- ctx = propagator.extract(self._carrier_getter, carrier)
- span = get_current_span(ctx)
- if span is not None:
- otel_context = span.get_span_context()
- else:
- otel_context = INVALID_SPAN_CONTEXT
-
- return SpanContextShim(otel_context)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/util.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/util.py
deleted file mode 100644
index eb7d3d9acaa..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/util.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# A default event name to be used for logging events when a better event name
-# can't be derived from the event's key-value pairs.
-DEFAULT_EVENT_NAME = "log"
-
-
-def time_seconds_to_ns(time_seconds):
- """Converts a time value in seconds to a time value in nanoseconds.
-
- `time_seconds` is a `float` as returned by `time.time()` which represents
- the number of seconds since the epoch.
-
- The returned value is an `int` representing the number of nanoseconds since
- the epoch.
- """
-
- return int(time_seconds * 1e9)
-
-
-def time_seconds_from_ns(time_nanoseconds):
- """Converts a time value in nanoseconds to a time value in seconds.
-
- `time_nanoseconds` is an `int` representing the number of nanoseconds since
- the epoch.
-
- The returned value is a `float` representing the number of seconds since
- the epoch.
- """
-
- return time_nanoseconds / 1e9
-
-
-def event_name_from_kv(key_values):
- """A helper function which returns an event name from the given dict, or a
- default event name.
- """
-
- if key_values is None or "event" not in key_values:
- return DEFAULT_EVENT_NAME
-
- return key_values["event"]
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/version.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_shim.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_shim.py
deleted file mode 100644
index 151ca07ba9e..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_shim.py
+++ /dev/null
@@ -1,636 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# TODO: make pylint use 3p opentracing module for type inference
-# pylint:disable=no-member
-
-import time
-from unittest import TestCase
-from unittest.mock import Mock
-
-import opentracing
-
-from opentelemetry import propagators, trace
-from opentelemetry.instrumentation.opentracing_shim import (
- SpanContextShim,
- SpanShim,
- create_tracer,
- util,
-)
-from opentelemetry.sdk.trace import TracerProvider
-from opentelemetry.test.mock_textmap import (
- MockTextMapPropagator,
- NOOPTextMapPropagator,
-)
-
-
-class TestShim(TestCase):
- # pylint: disable=too-many-public-methods
-
- def setUp(self):
- """Create an OpenTelemetry tracer and a shim before every test case."""
- trace.set_tracer_provider(TracerProvider())
- self.shim = create_tracer(trace.get_tracer_provider())
-
- @classmethod
- def setUpClass(cls):
- # Save current propagator to be restored on teardown.
- cls._previous_propagator = propagators.get_global_textmap()
-
- # Set mock propagator for testing.
- propagators.set_global_textmap(MockTextMapPropagator())
-
- @classmethod
- def tearDownClass(cls):
- # Restore previous propagator.
- propagators.set_global_textmap(cls._previous_propagator)
-
- def test_shim_type(self):
- # Verify shim is an OpenTracing tracer.
- self.assertIsInstance(self.shim, opentracing.Tracer)
-
- def test_start_active_span(self):
- """Test span creation and activation using `start_active_span()`."""
-
- with self.shim.start_active_span("TestSpan0") as scope:
- # Verify correct type of Scope and Span objects.
- self.assertIsInstance(scope, opentracing.Scope)
- self.assertIsInstance(scope.span, opentracing.Span)
-
- # Verify span is started.
- self.assertIsNotNone(scope.span.unwrap().start_time)
-
- # Verify span is active.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- scope.span.context.unwrap(),
- )
- # TODO: We can't check for equality of self.shim.active_span and
- # scope.span because the same OpenTelemetry span is returned inside
- # different SpanShim objects. A possible solution is described
- # here:
- # https://github.com/open-telemetry/opentelemetry-python/issues/161#issuecomment-534136274
-
- # Verify span has ended.
- self.assertIsNotNone(scope.span.unwrap().end_time)
-
- # Verify no span is active.
- self.assertIsNone(self.shim.active_span)
-
- def test_start_span(self):
- """Test span creation using `start_span()`."""
-
- with self.shim.start_span("TestSpan1") as span:
- # Verify correct type of Span object.
- self.assertIsInstance(span, opentracing.Span)
-
- # Verify span is started.
- self.assertIsNotNone(span.unwrap().start_time)
-
- # Verify `start_span()` does NOT make the span active.
- self.assertIsNone(self.shim.active_span)
-
- # Verify span has ended.
- self.assertIsNotNone(span.unwrap().end_time)
-
- def test_start_span_no_contextmanager(self):
- """Test `start_span()` without a `with` statement."""
-
- span = self.shim.start_span("TestSpan2")
-
- # Verify span is started.
- self.assertIsNotNone(span.unwrap().start_time)
-
- # Verify `start_span()` does NOT make the span active.
- self.assertIsNone(self.shim.active_span)
-
- span.finish()
-
- def test_explicit_span_finish(self):
- """Test `finish()` method on `Span` objects."""
-
- span = self.shim.start_span("TestSpan3")
-
- # Verify span hasn't ended.
- self.assertIsNone(span.unwrap().end_time)
-
- span.finish()
-
- # Verify span has ended.
- self.assertIsNotNone(span.unwrap().end_time)
-
- def test_explicit_start_time(self):
- """Test `start_time` argument."""
-
- now = time.time()
- with self.shim.start_active_span("TestSpan4", start_time=now) as scope:
- result = util.time_seconds_from_ns(scope.span.unwrap().start_time)
- # Tolerate inaccuracies of less than a microsecond. See Note:
- # https://open-telemetry.github.io/opentelemetry-python/opentelemetry.instrumentation.opentracing_shim.html
- # TODO: This seems to work consistently, but we should find out the
- # biggest possible loss of precision.
- self.assertAlmostEqual(result, now, places=6)
-
- def test_explicit_end_time(self):
- """Test `end_time` argument of `finish()` method."""
-
- span = self.shim.start_span("TestSpan5")
- now = time.time()
- span.finish(now)
-
- end_time = util.time_seconds_from_ns(span.unwrap().end_time)
- # Tolerate inaccuracies of less than a microsecond. See Note:
- # https://open-telemetry.github.io/opentelemetry-python/opentelemetry.instrumentation.opentracing_shim.html
- # TODO: This seems to work consistently, but we should find out the
- # biggest possible loss of precision.
- self.assertAlmostEqual(end_time, now, places=6)
-
- def test_explicit_span_activation(self):
- """Test manual activation and deactivation of a span."""
-
- span = self.shim.start_span("TestSpan6")
-
- # Verify no span is currently active.
- self.assertIsNone(self.shim.active_span)
-
- with self.shim.scope_manager.activate(
- span, finish_on_close=True
- ) as scope:
- # Verify span is active.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- scope.span.context.unwrap(),
- )
-
- # Verify no span is active.
- self.assertIsNone(self.shim.active_span)
-
- def test_start_active_span_finish_on_close(self):
- """Test `finish_on_close` argument of `start_active_span()`."""
-
- with self.shim.start_active_span(
- "TestSpan7", finish_on_close=True
- ) as scope:
- # Verify span hasn't ended.
- self.assertIsNone(scope.span.unwrap().end_time)
-
- # Verify span has ended.
- self.assertIsNotNone(scope.span.unwrap().end_time)
-
- with self.shim.start_active_span(
- "TestSpan8", finish_on_close=False
- ) as scope:
- # Verify span hasn't ended.
- self.assertIsNone(scope.span.unwrap().end_time)
-
- # Verify span hasn't ended after scope had been closed.
- self.assertIsNone(scope.span.unwrap().end_time)
-
- scope.span.finish()
-
- def test_activate_finish_on_close(self):
- """Test `finish_on_close` argument of `activate()`."""
-
- span = self.shim.start_span("TestSpan9")
-
- with self.shim.scope_manager.activate(
- span, finish_on_close=True
- ) as scope:
- # Verify span is active.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- scope.span.context.unwrap(),
- )
-
- # Verify span has ended.
- self.assertIsNotNone(span.unwrap().end_time)
-
- span = self.shim.start_span("TestSpan10")
-
- with self.shim.scope_manager.activate(
- span, finish_on_close=False
- ) as scope:
- # Verify span is active.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- scope.span.context.unwrap(),
- )
-
- # Verify span hasn't ended.
- self.assertIsNone(span.unwrap().end_time)
-
- span.finish()
-
- def test_explicit_scope_close(self):
- """Test `close()` method on `ScopeShim`."""
-
- with self.shim.start_active_span("ParentSpan") as parent:
- # Verify parent span is active.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- parent.span.context.unwrap(),
- )
-
- child = self.shim.start_active_span("ChildSpan")
-
- # Verify child span is active.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- child.span.context.unwrap(),
- )
-
- # Verify child span hasn't ended.
- self.assertIsNone(child.span.unwrap().end_time)
-
- child.close()
-
- # Verify child span has ended.
- self.assertIsNotNone(child.span.unwrap().end_time)
-
- # Verify parent span becomes active again.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- parent.span.context.unwrap(),
- )
-
- def test_parent_child_implicit(self):
- """Test parent-child relationship and activation/deactivation of spans
- without specifying the parent span upon creation.
- """
-
- with self.shim.start_active_span("ParentSpan") as parent:
- # Verify parent span is the active span.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- parent.span.context.unwrap(),
- )
-
- with self.shim.start_active_span("ChildSpan") as child:
- # Verify child span is the active span.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- child.span.context.unwrap(),
- )
-
- # Verify parent-child relationship.
- parent_trace_id = (
- parent.span.unwrap().get_span_context().trace_id
- )
- child_trace_id = (
- child.span.unwrap().get_span_context().trace_id
- )
-
- self.assertEqual(parent_trace_id, child_trace_id)
- self.assertEqual(
- child.span.unwrap().parent,
- parent.span.unwrap().get_span_context(),
- )
-
- # Verify parent span becomes the active span again.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- parent.span.context.unwrap()
- # TODO: Check equality of the spans themselves rather than
- # their context once the SpanShim reconstruction problem has
- # been addressed (see previous TODO).
- )
-
- # Verify there is no active span.
- self.assertIsNone(self.shim.active_span)
-
- def test_parent_child_explicit_span(self):
- """Test parent-child relationship of spans when specifying a `Span`
- object as a parent upon creation.
- """
-
- with self.shim.start_span("ParentSpan") as parent:
- with self.shim.start_active_span(
- "ChildSpan", child_of=parent
- ) as child:
- parent_trace_id = parent.unwrap().get_span_context().trace_id
- child_trace_id = (
- child.span.unwrap().get_span_context().trace_id
- )
-
- self.assertEqual(child_trace_id, parent_trace_id)
- self.assertEqual(
- child.span.unwrap().parent,
- parent.unwrap().get_span_context(),
- )
-
- with self.shim.start_span("ParentSpan") as parent:
- child = self.shim.start_span("ChildSpan", child_of=parent)
-
- parent_trace_id = parent.unwrap().get_span_context().trace_id
- child_trace_id = child.unwrap().get_span_context().trace_id
-
- self.assertEqual(child_trace_id, parent_trace_id)
- self.assertEqual(
- child.unwrap().parent, parent.unwrap().get_span_context()
- )
-
- child.finish()
-
- def test_parent_child_explicit_span_context(self):
- """Test parent-child relationship of spans when specifying a
- `SpanContext` object as a parent upon creation.
- """
-
- with self.shim.start_span("ParentSpan") as parent:
- with self.shim.start_active_span(
- "ChildSpan", child_of=parent.context
- ) as child:
- parent_trace_id = parent.unwrap().get_span_context().trace_id
- child_trace_id = (
- child.span.unwrap().get_span_context().trace_id
- )
-
- self.assertEqual(child_trace_id, parent_trace_id)
- self.assertEqual(
- child.span.unwrap().parent, parent.context.unwrap()
- )
-
- with self.shim.start_span("ParentSpan") as parent:
- with self.shim.start_span(
- "SpanWithContextParent", child_of=parent.context
- ) as child:
- parent_trace_id = parent.unwrap().get_span_context().trace_id
- child_trace_id = child.unwrap().get_span_context().trace_id
-
- self.assertEqual(child_trace_id, parent_trace_id)
- self.assertEqual(
- child.unwrap().parent, parent.context.unwrap()
- )
-
- def test_references(self):
- """Test span creation using the `references` argument."""
-
- with self.shim.start_span("ParentSpan") as parent:
- ref = opentracing.child_of(parent.context)
-
- with self.shim.start_active_span(
- "ChildSpan", references=[ref]
- ) as child:
- self.assertEqual(
- child.span.unwrap().links[0].context,
- parent.context.unwrap(),
- )
-
- def test_set_operation_name(self):
- """Test `set_operation_name()` method."""
-
- with self.shim.start_active_span("TestName") as scope:
- self.assertEqual(scope.span.unwrap().name, "TestName")
-
- scope.span.set_operation_name("NewName")
- self.assertEqual(scope.span.unwrap().name, "NewName")
-
- def test_tags(self):
- """Test tags behavior using the `tags` argument and the `set_tags()`
- method.
- """
-
- tags = {"foo": "bar"}
- with self.shim.start_active_span("TestSetTag", tags=tags) as scope:
- scope.span.set_tag("baz", "qux")
-
- self.assertEqual(scope.span.unwrap().attributes["foo"], "bar")
- self.assertEqual(scope.span.unwrap().attributes["baz"], "qux")
-
- def test_span_tracer(self):
- """Test the `tracer` property on `Span` objects."""
-
- with self.shim.start_active_span("TestSpan11") as scope:
- self.assertEqual(scope.span.tracer, self.shim)
-
- def test_log_kv(self):
- """Test the `log_kv()` method on `Span` objects."""
-
- with self.shim.start_span("TestSpan12") as span:
- span.log_kv({"foo": "bar"})
- self.assertEqual(span.unwrap().events[0].attributes["foo"], "bar")
- # Verify timestamp was generated automatically.
- self.assertIsNotNone(span.unwrap().events[0].timestamp)
-
- # Test explicit timestamp.
- now = time.time()
- span.log_kv({"foo": "bar"}, now)
- result = util.time_seconds_from_ns(
- span.unwrap().events[1].timestamp
- )
- self.assertEqual(span.unwrap().events[1].attributes["foo"], "bar")
- # Tolerate inaccuracies of less than a microsecond. See Note:
- # https://open-telemetry.github.io/opentelemetry-python/instrumentation/opentracing_shim/opentracing_shim.html
- # TODO: This seems to work consistently, but we should find out the
- # biggest possible loss of precision.
- self.assertAlmostEqual(result, now, places=6)
-
- def test_log(self):
- """Test the deprecated `log` method on `Span` objects."""
-
- with self.shim.start_span("TestSpan13") as span:
- with self.assertWarns(DeprecationWarning):
- span.log(event="foo", payload="bar")
-
- self.assertEqual(span.unwrap().events[0].attributes["event"], "foo")
- self.assertEqual(span.unwrap().events[0].attributes["payload"], "bar")
- self.assertIsNotNone(span.unwrap().events[0].timestamp)
-
- def test_log_event(self):
- """Test the deprecated `log_event` method on `Span` objects."""
-
- with self.shim.start_span("TestSpan14") as span:
- with self.assertWarns(DeprecationWarning):
- span.log_event("foo", "bar")
-
- self.assertEqual(span.unwrap().events[0].attributes["event"], "foo")
- self.assertEqual(span.unwrap().events[0].attributes["payload"], "bar")
- self.assertIsNotNone(span.unwrap().events[0].timestamp)
-
- def test_span_context(self):
- """Test construction of `SpanContextShim` objects."""
-
- otel_context = trace.SpanContext(1234, 5678, is_remote=False)
- context = SpanContextShim(otel_context)
-
- self.assertIsInstance(context, opentracing.SpanContext)
- self.assertEqual(context.unwrap().trace_id, 1234)
- self.assertEqual(context.unwrap().span_id, 5678)
-
- def test_span_on_error(self):
- """Verify error tag and logs are created on span when an exception is
- raised.
- """
-
- # Raise an exception while a span is active.
- with self.assertRaises(Exception):
- with self.shim.start_active_span("TestName") as scope:
- raise Exception
-
- # Verify exception details have been added to span.
- self.assertEqual(scope.span.unwrap().attributes["error"], True)
-
- def test_inject_http_headers(self):
- """Test `inject()` method for Format.HTTP_HEADERS."""
-
- otel_context = trace.SpanContext(
- trace_id=1220, span_id=7478, is_remote=False
- )
- context = SpanContextShim(otel_context)
-
- headers = {}
- self.shim.inject(context, opentracing.Format.HTTP_HEADERS, headers)
- self.assertEqual(
- headers[MockTextMapPropagator.TRACE_ID_KEY], str(1220)
- )
- self.assertEqual(headers[MockTextMapPropagator.SPAN_ID_KEY], str(7478))
-
- def test_inject_text_map(self):
- """Test `inject()` method for Format.TEXT_MAP."""
-
- otel_context = trace.SpanContext(
- trace_id=1220, span_id=7478, is_remote=False
- )
- context = SpanContextShim(otel_context)
-
- # Verify Format.TEXT_MAP
- text_map = {}
- self.shim.inject(context, opentracing.Format.TEXT_MAP, text_map)
- self.assertEqual(
- text_map[MockTextMapPropagator.TRACE_ID_KEY], str(1220)
- )
- self.assertEqual(
- text_map[MockTextMapPropagator.SPAN_ID_KEY], str(7478)
- )
-
- def test_inject_binary(self):
- """Test `inject()` method for Format.BINARY."""
-
- otel_context = trace.SpanContext(
- trace_id=1220, span_id=7478, is_remote=False
- )
- context = SpanContextShim(otel_context)
-
- # Verify exception for non supported binary format.
- with self.assertRaises(opentracing.UnsupportedFormatException):
- self.shim.inject(context, opentracing.Format.BINARY, bytearray())
-
- def test_extract_http_headers(self):
- """Test `extract()` method for Format.HTTP_HEADERS."""
-
- carrier = {
- MockTextMapPropagator.TRACE_ID_KEY: 1220,
- MockTextMapPropagator.SPAN_ID_KEY: 7478,
- }
-
- ctx = self.shim.extract(opentracing.Format.HTTP_HEADERS, carrier)
- self.assertEqual(ctx.unwrap().trace_id, 1220)
- self.assertEqual(ctx.unwrap().span_id, 7478)
-
- def test_extract_empty_context_returns_invalid_context(self):
- """In the case where the propagator cannot extract a
- SpanContext, extract should return and invalid span context.
- """
- _old_propagator = propagators.get_global_textmap()
- propagators.set_global_textmap(NOOPTextMapPropagator())
- try:
- carrier = {}
-
- ctx = self.shim.extract(opentracing.Format.HTTP_HEADERS, carrier)
- self.assertEqual(ctx.unwrap(), trace.INVALID_SPAN_CONTEXT)
- finally:
- propagators.set_global_textmap(_old_propagator)
-
- def test_extract_text_map(self):
- """Test `extract()` method for Format.TEXT_MAP."""
-
- carrier = {
- MockTextMapPropagator.TRACE_ID_KEY: 1220,
- MockTextMapPropagator.SPAN_ID_KEY: 7478,
- }
-
- ctx = self.shim.extract(opentracing.Format.TEXT_MAP, carrier)
- self.assertEqual(ctx.unwrap().trace_id, 1220)
- self.assertEqual(ctx.unwrap().span_id, 7478)
-
- def test_extract_binary(self):
- """Test `extract()` method for Format.BINARY."""
-
- # Verify exception for non supported binary format.
- with self.assertRaises(opentracing.UnsupportedFormatException):
- self.shim.extract(opentracing.Format.BINARY, bytearray())
-
- def test_baggage(self):
-
- span_context_shim = SpanContextShim(
- trace.SpanContext(1234, 5678, is_remote=False)
- )
-
- baggage = span_context_shim.baggage
-
- with self.assertRaises(ValueError):
- baggage[1] = 3
-
- span_shim = SpanShim(Mock(), span_context_shim, Mock())
-
- span_shim.set_baggage_item(1, 2)
-
- self.assertTrue(span_shim.get_baggage_item(1), 2)
-
- def test_active(self):
- """Test that the active property and start_active_span return the same
- object"""
-
- # Verify no span is currently active.
- self.assertIsNone(self.shim.active_span)
-
- with self.shim.start_active_span("TestSpan15") as scope:
- # Verify span is active.
- self.assertEqual(
- self.shim.active_span.context.unwrap(),
- scope.span.context.unwrap(),
- )
-
- self.assertIs(self.shim.scope_manager.active, scope)
-
- # Verify no span is active.
- self.assertIsNone(self.shim.active_span)
-
- def test_mixed_mode(self):
- """Test that span parent-child relationship is kept between
- OpenTelemetry and the OpenTracing shim"""
-
- span_shim = self.shim.start_span("TestSpan16")
-
- with self.shim.scope_manager.activate(span_shim, finish_on_close=True):
-
- with (
- TracerProvider()
- .get_tracer(__name__)
- .start_as_current_span("abc")
- ) as opentelemetry_span:
-
- self.assertIs(
- span_shim.unwrap().context, opentelemetry_span.parent,
- )
-
- with (
- TracerProvider().get_tracer(__name__).start_as_current_span("abc")
- ) as opentelemetry_span:
-
- with self.shim.start_active_span("TestSpan17") as scope:
-
- self.assertIs(
- scope.span.unwrap().parent, opentelemetry_span.context,
- )
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_util.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_util.py
deleted file mode 100644
index 806a8da609b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_util.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright The OpenTelemetry 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 time
-import unittest
-
-from opentelemetry.instrumentation.opentracing_shim import util
-from opentelemetry.util import time_ns
-
-
-class TestUtil(unittest.TestCase):
- def test_event_name_from_kv(self):
- # Test basic behavior.
- event_name = "send HTTP request"
- res = util.event_name_from_kv({"event": event_name, "foo": "bar"})
- self.assertEqual(res, event_name)
-
- # Test None.
- res = util.event_name_from_kv(None)
- self.assertEqual(res, util.DEFAULT_EVENT_NAME)
-
- # Test empty dict.
- res = util.event_name_from_kv({})
- self.assertEqual(res, util.DEFAULT_EVENT_NAME)
-
- # Test missing `event` field.
- res = util.event_name_from_kv({"foo": "bar"})
- self.assertEqual(res, util.DEFAULT_EVENT_NAME)
-
- def test_time_seconds_to_ns(self):
- time_seconds = time.time()
- result = util.time_seconds_to_ns(time_seconds)
-
- self.assertEqual(result, int(time_seconds * 1e9))
-
- def test_time_seconds_from_ns(self):
- time_nanoseconds = time_ns()
- result = util.time_seconds_from_ns(time_nanoseconds)
-
- self.assertEqual(result, time_nanoseconds / 1e9)
-
- def test_time_conversion_precision(self):
- """Verify time conversion from seconds to nanoseconds and vice versa is
- accurate enough.
- """
-
- time_seconds = 1570484241.9501917
- time_nanoseconds = util.time_seconds_to_ns(time_seconds)
- result = util.time_seconds_from_ns(time_nanoseconds)
-
- # Tolerate inaccuracies of less than a microsecond.
- # TODO: Put a link to an explanation in the docs.
- # TODO: This seems to work consistently, but we should find out the
- # biggest possible loss of precision.
- self.assertAlmostEqual(result, time_seconds, places=6)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/README.rst
deleted file mode 100644
index ba7119cd68c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/README.rst
+++ /dev/null
@@ -1,47 +0,0 @@
-
-Testbed suite for the OpenTelemetry-OpenTracing Bridge
-======================================================
-
-Testbed suite designed to test the API changes.
-
-Build and test.
----------------
-
-.. code-block:: sh
-
- tox -e py37-test-opentracing-shim
-
-Alternatively, due to the organization of the suite, it's possible to run directly the tests using ``py.test``\ :
-
-.. code-block:: sh
-
- py.test -s testbed/test_multiple_callbacks/test_threads.py
-
-Tested frameworks
------------------
-
-Currently the examples cover ``threading`` and ``asyncio``.
-
-List of patterns
-----------------
-
-
-* `Active Span replacement `_ - Start an isolated task and query for its results in another task/thread.
-* `Client-Server `_ - Typical client-server example.
-* `Common Request Handler `_ - One request handler for all requests.
-* `Late Span finish `_ - Late parent ``Span`` finish.
-* `Multiple callbacks `_ - Multiple callbacks spawned at the same time.
-* `Nested callbacks `_ - One callback at a time, defined in a pipeline fashion.
-* `Subtask Span propagation `_ - ``Span`` propagation for subtasks/coroutines.
-
-Adding new patterns
--------------------
-
-A new pattern is composed of a directory under *testbed* with the *test_* prefix, and containing the files for each platform, also with the *test_* prefix:
-
-.. code-block::
-
- testbed/
- test_new_pattern/
- test_threads.py
- test_asyncio.py
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/otel_ot_shim_tracer.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/otel_ot_shim_tracer.py
deleted file mode 100644
index c12bbfa0291..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/otel_ot_shim_tracer.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import opentelemetry.instrumentation.opentracing_shim as opentracingshim
-from opentelemetry.sdk import trace
-from opentelemetry.sdk.trace.export import SimpleExportSpanProcessor
-from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
- InMemorySpanExporter,
-)
-
-
-class MockTracer(opentracingshim.TracerShim):
- """Wrapper of `opentracingshim.TracerShim`.
-
- MockTracer extends `opentracingshim.TracerShim` by adding a in memory
- span exporter that can be used to get the list of finished spans."""
-
- def __init__(self):
- tracer_provider = trace.TracerProvider()
- oteltracer = tracer_provider.get_tracer(__name__)
- super(MockTracer, self).__init__(oteltracer)
- exporter = InMemorySpanExporter()
- span_processor = SimpleExportSpanProcessor(exporter)
- tracer_provider.add_span_processor(span_processor)
-
- self.exporter = exporter
-
- def finished_spans(self):
- return self.exporter.get_finished_spans()
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/README.rst
deleted file mode 100644
index 6bb4d2f35c6..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/README.rst
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Active Span replacement example.
-================================
-
-This example shows a ``Span`` being created and then passed to an asynchronous task, which will temporary activate it to finish its processing, and further restore the previously active ``Span``.
-
-``threading`` implementation:
-
-.. code-block:: python
-
- # Create a new Span for this task
- with self.tracer.start_active_span("task"):
-
- with self.tracer.scope_manager.activate(span, True):
- # Simulate work strictly related to the initial Span
- pass
-
- # Use the task span as parent of a new subtask
- with self.tracer.start_active_span("subtask"):
- pass
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/test_asyncio.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/test_asyncio.py
deleted file mode 100644
index cb555dc1092..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/test_asyncio.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from __future__ import print_function
-
-import asyncio
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import stop_loop_when
-
-
-class TestAsyncio(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.loop = asyncio.get_event_loop()
-
- def test_main(self):
- # Start an isolated task and query for its result -and finish it-
- # in another task/thread
- span = self.tracer.start_span("initial")
- self.submit_another_task(span)
-
- stop_loop_when(
- self.loop,
- lambda: len(self.tracer.finished_spans()) >= 3,
- timeout=5.0,
- )
- self.loop.run_forever()
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 3)
- self.assertNamesEqual(spans, ["initial", "subtask", "task"])
-
- # task/subtask are part of the same trace,
- # and subtask is a child of task
- self.assertSameTrace(spans[1], spans[2])
- self.assertIsChildOf(spans[1], spans[2])
-
- # initial task is not related in any way to those two tasks
- self.assertNotSameTrace(spans[0], spans[1])
- self.assertEqual(spans[0].parent, None)
-
- async def task(self, span):
- # Create a new Span for this task
- with self.tracer.start_active_span("task"):
-
- with self.tracer.scope_manager.activate(span, True):
- # Simulate work strictly related to the initial Span
- pass
-
- # Use the task span as parent of a new subtask
- with self.tracer.start_active_span("subtask"):
- pass
-
- def submit_another_task(self, span):
- self.loop.create_task(self.task(span))
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/test_threads.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/test_threads.py
deleted file mode 100644
index e382d5d7167..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_active_span_replacement/test_threads.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from __future__ import print_function
-
-from concurrent.futures import ThreadPoolExecutor
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-
-
-class TestThreads(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- # use max_workers=3 as a general example even if only one would suffice
- self.executor = ThreadPoolExecutor(max_workers=3)
-
- def test_main(self):
- # Start an isolated task and query for its result -and finish it-
- # in another task/thread
- span = self.tracer.start_span("initial")
- self.submit_another_task(span)
-
- self.executor.shutdown(True)
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 3)
- self.assertNamesEqual(spans, ["initial", "subtask", "task"])
-
- # task/subtask are part of the same trace,
- # and subtask is a child of task
- self.assertSameTrace(spans[1], spans[2])
- self.assertIsChildOf(spans[1], spans[2])
-
- # initial task is not related in any way to those two tasks
- self.assertNotSameTrace(spans[0], spans[1])
- self.assertEqual(spans[0].parent, None)
- self.assertEqual(spans[2].parent, None)
-
- def task(self, span):
- # Create a new Span for this task
- with self.tracer.start_active_span("task"):
-
- with self.tracer.scope_manager.activate(span, True):
- # Simulate work strictly related to the initial Span
- pass
-
- # Use the task span as parent of a new subtask
- with self.tracer.start_active_span("subtask"):
- pass
-
- def submit_another_task(self, span):
- self.executor.submit(self.task, span)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/README.rst
deleted file mode 100644
index 730fd9295da..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/README.rst
+++ /dev/null
@@ -1,19 +0,0 @@
-
-Client-Server example.
-======================
-
-This example shows a ``Span`` created by a ``Client``, which will send a ``Message`` / ``SpanContext`` to a ``Server``, which will in turn extract such context and use it as parent of a new (server-side) ``Span``.
-
-``Client.send()`` is used to send messages and inject the ``SpanContext`` using the ``TEXT_MAP`` format, and ``Server.process()`` will process received messages and will extract the context used as parent.
-
-.. code-block:: python
-
- def send(self):
- with self.tracer.start_active_span("send") as scope:
- scope.span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
-
- message = {}
- self.tracer.inject(scope.span.context,
- opentracing.Format.TEXT_MAP,
- message)
- self.queue.put(message)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/test_asyncio.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/test_asyncio.py
deleted file mode 100644
index 5379584719a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/test_asyncio.py
+++ /dev/null
@@ -1,79 +0,0 @@
-from __future__ import print_function
-
-import asyncio
-
-import opentracing
-from opentracing.ext import tags
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import get_logger, get_one_by_tag, stop_loop_when
-
-logger = get_logger(__name__)
-
-
-class Server:
- def __init__(self, *args, **kwargs):
- tracer = kwargs.pop("tracer")
- queue = kwargs.pop("queue")
- super(Server, self).__init__(*args, **kwargs)
-
- self.tracer = tracer
- self.queue = queue
-
- async def run(self):
- value = await self.queue.get()
- self.process(value)
-
- def process(self, message):
- logger.info("Processing message in server")
-
- ctx = self.tracer.extract(opentracing.Format.TEXT_MAP, message)
- with self.tracer.start_active_span("receive", child_of=ctx) as scope:
- scope.span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_SERVER)
-
-
-class Client:
- def __init__(self, tracer, queue):
- self.tracer = tracer
- self.queue = queue
-
- async def send(self):
- with self.tracer.start_active_span("send") as scope:
- scope.span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
-
- message = {}
- self.tracer.inject(
- scope.span.context, opentracing.Format.TEXT_MAP, message
- )
- await self.queue.put(message)
-
- logger.info("Sent message from client")
-
-
-class TestAsyncio(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.queue = asyncio.Queue()
- self.loop = asyncio.get_event_loop()
- self.server = Server(tracer=self.tracer, queue=self.queue)
-
- def test(self):
- client = Client(self.tracer, self.queue)
- self.loop.create_task(self.server.run())
- self.loop.create_task(client.send())
-
- stop_loop_when(
- self.loop,
- lambda: len(self.tracer.finished_spans()) >= 2,
- timeout=5.0,
- )
- self.loop.run_forever()
-
- spans = self.tracer.finished_spans()
- self.assertIsNotNone(
- get_one_by_tag(spans, tags.SPAN_KIND, tags.SPAN_KIND_RPC_SERVER)
- )
- self.assertIsNotNone(
- get_one_by_tag(spans, tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
- )
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/test_threads.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/test_threads.py
deleted file mode 100644
index 619781edecf..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_client_server/test_threads.py
+++ /dev/null
@@ -1,75 +0,0 @@
-from __future__ import print_function
-
-from queue import Queue
-from threading import Thread
-
-import opentracing
-from opentracing.ext import tags
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import await_until, get_logger, get_one_by_tag
-
-logger = get_logger(__name__)
-
-
-class Server(Thread):
- def __init__(self, *args, **kwargs):
- tracer = kwargs.pop("tracer")
- queue = kwargs.pop("queue")
- super(Server, self).__init__(*args, **kwargs)
-
- self.daemon = True
- self.tracer = tracer
- self.queue = queue
-
- def run(self):
- value = self.queue.get()
- self.process(value)
-
- def process(self, message):
- logger.info("Processing message in server")
-
- ctx = self.tracer.extract(opentracing.Format.TEXT_MAP, message)
- with self.tracer.start_active_span("receive", child_of=ctx) as scope:
- scope.span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_SERVER)
-
-
-class Client:
- def __init__(self, tracer, queue):
- self.tracer = tracer
- self.queue = queue
-
- def send(self):
- with self.tracer.start_active_span("send") as scope:
- scope.span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
-
- message = {}
- self.tracer.inject(
- scope.span.context, opentracing.Format.TEXT_MAP, message
- )
- self.queue.put(message)
-
- logger.info("Sent message from client")
-
-
-class TestThreads(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.queue = Queue()
- self.server = Server(tracer=self.tracer, queue=self.queue)
- self.server.start()
-
- def test(self):
- client = Client(self.tracer, self.queue)
- client.send()
-
- await_until(lambda: len(self.tracer.finished_spans()) >= 2)
-
- spans = self.tracer.finished_spans()
- self.assertIsNotNone(
- get_one_by_tag(spans, tags.SPAN_KIND, tags.SPAN_KIND_RPC_SERVER)
- )
- self.assertIsNotNone(
- get_one_by_tag(spans, tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
- )
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/README.rst
deleted file mode 100644
index 1bcda539bbd..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/README.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-
-Common Request Handler example.
-===============================
-
-This example shows a ``Span`` used with ``RequestHandler``, which is used as a middleware (as in web frameworks) to manage a new ``Span`` per operation through its ``before_request()`` / ``after_response()`` methods.
-
-Implementation details:
-
-
-* For ``threading``, no active ``Span`` is consumed as the tasks may be run concurrently on different threads, and an explicit ``SpanContext`` has to be saved to be used as parent.
-
-RequestHandler implementation:
-
-.. code-block:: python
-
- def before_request(self, request, request_context):
-
- # If we should ignore the active Span, use any passed SpanContext
- # as the parent. Else, use the active one.
- span = self.tracer.start_span("send",
- child_of=self.context,
- ignore_active_span=True)
-
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/request_handler.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/request_handler.py
deleted file mode 100644
index 47ff088025a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/request_handler.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from __future__ import print_function
-
-from opentracing.ext import tags
-
-from ..utils import get_logger
-
-logger = get_logger(__name__)
-
-
-class RequestHandler:
- def __init__(self, tracer, context=None, ignore_active_span=True):
- self.tracer = tracer
- self.context = context
- self.ignore_active_span = ignore_active_span
-
- def before_request(self, request, request_context):
- logger.info("Before request %s", request)
-
- # If we should ignore the active Span, use any passed SpanContext
- # as the parent. Else, use the active one.
- if self.ignore_active_span:
- span = self.tracer.start_span(
- "send", child_of=self.context, ignore_active_span=True
- )
- else:
- span = self.tracer.start_span("send")
-
- span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
-
- request_context["span"] = span
-
- def after_request(self, request, request_context):
- # pylint: disable=no-self-use
- logger.info("After request %s", request)
-
- span = request_context.get("span")
- if span is not None:
- span.finish()
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/test_asyncio.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/test_asyncio.py
deleted file mode 100644
index b0216dd7560..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/test_asyncio.py
+++ /dev/null
@@ -1,136 +0,0 @@
-from __future__ import print_function
-
-import asyncio
-
-from opentracing.ext import tags
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import get_logger, get_one_by_operation_name, stop_loop_when
-from .request_handler import RequestHandler
-
-logger = get_logger(__name__)
-
-
-class Client:
- def __init__(self, request_handler, loop):
- self.request_handler = request_handler
- self.loop = loop
-
- async def send_task(self, message):
- request_context = {}
-
- async def before_handler():
- self.request_handler.before_request(message, request_context)
-
- async def after_handler():
- self.request_handler.after_request(message, request_context)
-
- await before_handler()
- await after_handler()
-
- return "%s::response" % message
-
- def send(self, message):
- return self.send_task(message)
-
- def send_sync(self, message):
- return self.loop.run_until_complete(self.send_task(message))
-
-
-class TestAsyncio(OpenTelemetryTestCase):
- """
- There is only one instance of 'RequestHandler' per 'Client'. Methods of
- 'RequestHandler' are executed in different Tasks, and no Span propagation
- among them is done automatically.
- Therefore we cannot use current active span and activate span.
- So one issue here is setting correct parent span.
- """
-
- def setUp(self):
- self.tracer = MockTracer()
- self.loop = asyncio.get_event_loop()
- self.client = Client(RequestHandler(self.tracer), self.loop)
-
- def test_two_callbacks(self):
- res_future1 = self.loop.create_task(self.client.send("message1"))
- res_future2 = self.loop.create_task(self.client.send("message2"))
-
- stop_loop_when(
- self.loop,
- lambda: len(self.tracer.finished_spans()) >= 2,
- timeout=5.0,
- )
- self.loop.run_forever()
-
- self.assertEqual("message1::response", res_future1.result())
- self.assertEqual("message2::response", res_future2.result())
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 2)
-
- for span in spans:
- self.assertEqual(
- span.attributes.get(tags.SPAN_KIND, None),
- tags.SPAN_KIND_RPC_CLIENT,
- )
-
- self.assertNotSameTrace(spans[0], spans[1])
- self.assertIsNone(spans[0].parent)
- self.assertIsNone(spans[1].parent)
-
- def test_parent_not_picked(self):
- """Active parent should not be picked up by child."""
-
- async def do_task():
- with self.tracer.start_active_span("parent"):
- response = await self.client.send_task("no_parent")
- self.assertEqual("no_parent::response", response)
-
- self.loop.run_until_complete(do_task())
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 2)
-
- child_span = get_one_by_operation_name(spans, "send")
- self.assertIsNotNone(child_span)
-
- parent_span = get_one_by_operation_name(spans, "parent")
- self.assertIsNotNone(parent_span)
-
- # Here check that there is no parent-child relation.
- self.assertIsNotChildOf(child_span, parent_span)
-
- def test_good_solution_to_set_parent(self):
- """Asyncio and contextvars are integrated, in this case it is not needed
- to activate current span by hand.
- """
-
- async def do_task():
- with self.tracer.start_active_span("parent"):
- # Set ignore_active_span to False indicating that the
- # framework will do it for us.
- req_handler = RequestHandler(
- self.tracer, ignore_active_span=False,
- )
- client = Client(req_handler, self.loop)
- response = await client.send_task("correct_parent")
-
- self.assertEqual("correct_parent::response", response)
-
- # Send second request, now there is no active parent,
- # but it will be set, ups
- response = await client.send_task("wrong_parent")
- self.assertEqual("wrong_parent::response", response)
-
- self.loop.run_until_complete(do_task())
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 3)
-
- spans = sorted(spans, key=lambda x: x.start_time)
- parent_span = get_one_by_operation_name(spans, "parent")
- self.assertIsNotNone(parent_span)
-
- self.assertIsChildOf(spans[1], parent_span)
- self.assertIsNotChildOf(spans[2], parent_span)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/test_threads.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/test_threads.py
deleted file mode 100644
index 4ab8b2a075e..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_common_request_handler/test_threads.py
+++ /dev/null
@@ -1,119 +0,0 @@
-from __future__ import print_function
-
-from concurrent.futures import ThreadPoolExecutor
-
-from opentracing.ext import tags
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import get_logger, get_one_by_operation_name
-from .request_handler import RequestHandler
-
-logger = get_logger(__name__)
-
-
-class Client:
- def __init__(self, request_handler, executor):
- self.request_handler = request_handler
- self.executor = executor
-
- def send_task(self, message):
- request_context = {}
-
- def before_handler():
- self.request_handler.before_request(message, request_context)
-
- def after_handler():
- self.request_handler.after_request(message, request_context)
-
- self.executor.submit(before_handler).result()
- self.executor.submit(after_handler).result()
-
- return "%s::response" % message
-
- def send(self, message):
- return self.executor.submit(self.send_task, message)
-
- def send_sync(self, message, timeout=5.0):
- fut = self.executor.submit(self.send_task, message)
- return fut.result(timeout=timeout)
-
-
-class TestThreads(OpenTelemetryTestCase):
- """
- There is only one instance of 'RequestHandler' per 'Client'. Methods of
- 'RequestHandler' are executed concurrently in different threads which are
- reused (executor). Therefore we cannot use current active span and
- activate span. So one issue here is setting correct parent span.
- """
-
- def setUp(self):
- self.tracer = MockTracer()
- self.executor = ThreadPoolExecutor(max_workers=3)
- self.client = Client(RequestHandler(self.tracer), self.executor)
-
- def test_two_callbacks(self):
- response_future1 = self.client.send("message1")
- response_future2 = self.client.send("message2")
-
- self.assertEqual("message1::response", response_future1.result(5.0))
- self.assertEqual("message2::response", response_future2.result(5.0))
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 2)
-
- for span in spans:
- self.assertEqual(
- span.attributes.get(tags.SPAN_KIND, None),
- tags.SPAN_KIND_RPC_CLIENT,
- )
-
- self.assertNotSameTrace(spans[0], spans[1])
- self.assertIsNone(spans[0].parent)
- self.assertIsNone(spans[1].parent)
-
- def test_parent_not_picked(self):
- """Active parent should not be picked up by child."""
-
- with self.tracer.start_active_span("parent"):
- response = self.client.send_sync("no_parent")
- self.assertEqual("no_parent::response", response)
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 2)
-
- child_span = get_one_by_operation_name(spans, "send")
- self.assertIsNotNone(child_span)
-
- parent_span = get_one_by_operation_name(spans, "parent")
- self.assertIsNotNone(parent_span)
-
- # Here check that there is no parent-child relation.
- self.assertIsNotChildOf(child_span, parent_span)
-
- def test_bad_solution_to_set_parent(self):
- """Solution is bad because parent is per client and is not automatically
- activated depending on the context.
- """
-
- with self.tracer.start_active_span("parent") as scope:
- client = Client(
- # Pass a span context to be used ad the parent.
- RequestHandler(self.tracer, scope.span.context),
- self.executor,
- )
- response = client.send_sync("correct_parent")
- self.assertEqual("correct_parent::response", response)
-
- response = client.send_sync("wrong_parent")
- self.assertEqual("wrong_parent::response", response)
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 3)
-
- spans = sorted(spans, key=lambda x: x.start_time)
- parent_span = get_one_by_operation_name(spans, "parent")
- self.assertIsNotNone(parent_span)
-
- self.assertIsChildOf(spans[1], parent_span)
- self.assertIsChildOf(spans[2], parent_span)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/README.rst
deleted file mode 100644
index 8c4ffd864ac..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/README.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-
-Late Span finish example.
-=========================
-
-This example shows a ``Span`` for a top-level operation, with independent, unknown lifetime, acting as parent of a few asynchronous subtasks (which must re-activate it but not finish it).
-
-.. code-block:: python
-
- # Fire away a few subtasks, passing a parent Span whose lifetime
- # is not tied at all to the children.
- def submit_subtasks(self, parent_span):
- def task(name, interval):
- with self.tracer.scope_manager.activate(parent_span, False):
- with self.tracer.start_active_span(name):
- time.sleep(interval)
-
- self.executor.submit(task, "task1", 0.1)
- self.executor.submit(task, "task2", 0.3)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/test_asyncio.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/test_asyncio.py
deleted file mode 100644
index 128073b056f..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/test_asyncio.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from __future__ import print_function
-
-import asyncio
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import get_logger, stop_loop_when
-
-logger = get_logger(__name__)
-
-
-class TestAsyncio(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.loop = asyncio.get_event_loop()
-
- def test_main(self):
- # Create a Span and use it as (explicit) parent of a pair of subtasks.
- parent_span = self.tracer.start_span("parent")
- self.submit_subtasks(parent_span)
-
- stop_loop_when(
- self.loop,
- lambda: len(self.tracer.finished_spans()) >= 2,
- timeout=5.0,
- )
- self.loop.run_forever()
-
- # Late-finish the parent Span now.
- parent_span.finish()
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 3)
- self.assertNamesEqual(spans, ["task1", "task2", "parent"])
-
- for idx in range(2):
- self.assertSameTrace(spans[idx], spans[-1])
- self.assertIsChildOf(spans[idx], spans[-1])
- self.assertTrue(spans[idx].end_time <= spans[-1].end_time)
-
- # Fire away a few subtasks, passing a parent Span whose lifetime
- # is not tied at all to the children.
- def submit_subtasks(self, parent_span):
- async def task(name):
- logger.info("Running %s", name)
- with self.tracer.scope_manager.activate(parent_span, False):
- with self.tracer.start_active_span(name):
- await asyncio.sleep(0.1)
-
- self.loop.create_task(task("task1"))
- self.loop.create_task(task("task2"))
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/test_threads.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/test_threads.py
deleted file mode 100644
index 5972eb8b924..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_late_span_finish/test_threads.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from __future__ import print_function
-
-import time
-from concurrent.futures import ThreadPoolExecutor
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-
-
-class TestThreads(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.executor = ThreadPoolExecutor(max_workers=3)
-
- def test_main(self):
- # Create a Span and use it as (explicit) parent of a pair of subtasks.
- parent_span = self.tracer.start_span("parent")
- self.submit_subtasks(parent_span)
-
- # Wait for the threadpool to be done.
- self.executor.shutdown(True)
-
- # Late-finish the parent Span now.
- parent_span.finish()
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 3)
- self.assertNamesEqual(spans, ["task1", "task2", "parent"])
-
- for idx in range(2):
- self.assertSameTrace(spans[idx], spans[-1])
- self.assertIsChildOf(spans[idx], spans[-1])
- self.assertTrue(spans[idx].end_time <= spans[-1].end_time)
-
- # Fire away a few subtasks, passing a parent Span whose lifetime
- # is not tied at all to the children.
- def submit_subtasks(self, parent_span):
- def task(name, interval):
- with self.tracer.scope_manager.activate(parent_span, False):
- with self.tracer.start_active_span(name):
- time.sleep(interval)
-
- self.executor.submit(task, "task1", 0.1)
- self.executor.submit(task, "task2", 0.3)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/README.rst
deleted file mode 100644
index 952d1ec51dd..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/README.rst
+++ /dev/null
@@ -1,19 +0,0 @@
-
-Listener Response example.
-==========================
-
-This example shows a ``Span`` created upon a message being sent to a ``Client``, and its handling along a related, **not shared** ``ResponseListener`` object with a ``on_response(self, response)`` method to finish it.
-
-.. code-block:: python
-
- def _task(self, message, listener):
- res = "%s::response" % message
- listener.on_response(res)
- return res
-
- def send_sync(self, message):
- span = self.tracer.start_span("send")
- span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
-
- listener = ResponseListener(span)
- return self.executor.submit(self._task, message, listener).result()
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/response_listener.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/response_listener.py
deleted file mode 100644
index dd143c20b8e..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/response_listener.py
+++ /dev/null
@@ -1,7 +0,0 @@
-class ResponseListener:
- def __init__(self, span):
- self.span = span
-
- def on_response(self, res):
- del res
- self.span.finish()
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/test_asyncio.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/test_asyncio.py
deleted file mode 100644
index 085c0ea8134..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/test_asyncio.py
+++ /dev/null
@@ -1,45 +0,0 @@
-from __future__ import print_function
-
-import asyncio
-
-from opentracing.ext import tags
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import get_one_by_tag
-from .response_listener import ResponseListener
-
-
-class Client:
- def __init__(self, tracer, loop):
- self.tracer = tracer
- self.loop = loop
-
- async def task(self, message, listener):
- res = "%s::response" % message
- listener.on_response(res)
- return res
-
- def send_sync(self, message):
- span = self.tracer.start_span("send")
- span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
-
- listener = ResponseListener(span)
- return self.loop.run_until_complete(self.task(message, listener))
-
-
-class TestAsyncio(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.loop = asyncio.get_event_loop()
-
- def test_main(self):
- client = Client(self.tracer, self.loop)
- res = client.send_sync("message")
- self.assertEqual(res, "message::response")
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 1)
-
- span = get_one_by_tag(spans, tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
- self.assertIsNotNone(span)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/test_threads.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/test_threads.py
deleted file mode 100644
index 8f82e1fb158..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_listener_per_request/test_threads.py
+++ /dev/null
@@ -1,45 +0,0 @@
-from __future__ import print_function
-
-from concurrent.futures import ThreadPoolExecutor
-
-from opentracing.ext import tags
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import get_one_by_tag
-from .response_listener import ResponseListener
-
-
-class Client:
- def __init__(self, tracer):
- self.tracer = tracer
- self.executor = ThreadPoolExecutor(max_workers=3)
-
- def _task(self, message, listener):
- # pylint: disable=no-self-use
- res = "%s::response" % message
- listener.on_response(res)
- return res
-
- def send_sync(self, message):
- span = self.tracer.start_span("send")
- span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
-
- listener = ResponseListener(span)
- return self.executor.submit(self._task, message, listener).result()
-
-
-class TestThreads(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
-
- def test_main(self):
- client = Client(self.tracer)
- res = client.send_sync("message")
- self.assertEqual(res, "message::response")
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 1)
-
- span = get_one_by_tag(spans, tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
- self.assertIsNotNone(span)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/README.rst
deleted file mode 100644
index 204f282cf23..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/README.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-
-Multiple callbacks example.
-===========================
-
-This example shows a ``Span`` created for a top-level operation, covering a set of asynchronous operations (representing callbacks), and have this ``Span`` finished when **all** of them have been executed.
-
-``Client.send()`` is used to create a new asynchronous operation (callback), and in turn every operation both restores the active ``Span``, and creates a child ``Span`` (useful for measuring the performance of each callback).
-
-Implementation details:
-
-
-* For ``threading``, a thread-safe counter is put in each ``Span`` to keep track of the pending callbacks, and call ``Span.finish()`` when the count becomes 0.
-* For ``asyncio`` the children corotuines representing the subtasks are simply yielded over, so no counter is needed.
-
-``threading`` implementation:
-
-.. code-block:: python
-
- def task(self, interval, parent_span):
- logger.info("Starting task")
-
- try:
- scope = self.tracer.scope_manager.activate(parent_span, False)
- with self.tracer.start_active_span("task"):
- time.sleep(interval)
- finally:
- scope.close()
- if parent_span._ref_count.decr() == 0:
- parent_span.finish()
-
-``asyncio`` implementation:
-
-.. code-block:: python
-
- async def task(self, interval, parent_span):
- logger.info("Starting task")
-
- with self.tracer.start_active_span("task"):
- await asyncio.sleep(interval)
-
- # Invoke and yield over the corotuines.
- with self.tracer.start_active_span("parent"):
- tasks = self.submit_callbacks()
- await asyncio.gather(*tasks)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/test_asyncio.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/test_asyncio.py
deleted file mode 100644
index 36043d0a9bc..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/test_asyncio.py
+++ /dev/null
@@ -1,59 +0,0 @@
-from __future__ import print_function
-
-import asyncio
-import random
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import get_logger, stop_loop_when
-
-random.seed()
-logger = get_logger(__name__)
-
-
-class TestAsyncio(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.loop = asyncio.get_event_loop()
-
- def test_main(self):
- # Need to run within a Task, as the scope manager depends
- # on Task.current_task()
- async def main_task():
- with self.tracer.start_active_span("parent"):
- tasks = self.submit_callbacks()
- await asyncio.gather(*tasks)
-
- self.loop.create_task(main_task())
-
- stop_loop_when(
- self.loop,
- lambda: len(self.tracer.finished_spans()) >= 4,
- timeout=5.0,
- )
- self.loop.run_forever()
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 4)
- self.assertNamesEqual(spans, ["task", "task", "task", "parent"])
-
- for idx in range(3):
- self.assertSameTrace(spans[idx], spans[-1])
- self.assertIsChildOf(spans[idx], spans[-1])
-
- async def task(self, interval, parent_span):
- logger.info("Starting task")
-
- with self.tracer.scope_manager.activate(parent_span, False):
- with self.tracer.start_active_span("task"):
- await asyncio.sleep(interval)
-
- def submit_callbacks(self):
- parent_span = self.tracer.scope_manager.active.span
- tasks = []
- for _ in range(3):
- interval = 0.1 + random.randint(200, 500) * 0.001
- task = self.loop.create_task(self.task(interval, parent_span))
- tasks.append(task)
-
- return tasks
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/test_threads.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/test_threads.py
deleted file mode 100644
index b24ae643e36..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_multiple_callbacks/test_threads.py
+++ /dev/null
@@ -1,59 +0,0 @@
-from __future__ import print_function
-
-import random
-import time
-from concurrent.futures import ThreadPoolExecutor
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import RefCount, get_logger
-
-random.seed()
-logger = get_logger(__name__)
-
-
-class TestThreads(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.executor = ThreadPoolExecutor(max_workers=3)
-
- def test_main(self):
- try:
- scope = self.tracer.start_active_span(
- "parent", finish_on_close=False
- )
- scope.span.ref_count = RefCount(1)
- self.submit_callbacks(scope.span)
- finally:
- scope.close()
- if scope.span.ref_count.decr() == 0:
- scope.span.finish()
-
- self.executor.shutdown(True)
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 4)
- self.assertNamesEqual(spans, ["task", "task", "task", "parent"])
-
- for idx in range(3):
- self.assertSameTrace(spans[idx], spans[-1])
- self.assertIsChildOf(spans[idx], spans[-1])
-
- def task(self, interval, parent_span):
- logger.info("Starting task")
-
- try:
- scope = self.tracer.scope_manager.activate(parent_span, False)
- with self.tracer.start_active_span("task"):
- time.sleep(interval)
- finally:
- scope.close()
- if parent_span.ref_count.decr() == 0:
- parent_span.finish()
-
- def submit_callbacks(self, parent_span):
- for _ in range(3):
- parent_span.ref_count.incr()
- self.executor.submit(
- self.task, 0.1 + random.randint(200, 500) * 0.001, parent_span
- )
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/README.rst
deleted file mode 100644
index c191431ccc4..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/README.rst
+++ /dev/null
@@ -1,47 +0,0 @@
-
-Nested callbacks example.
-=========================
-
-This example shows a ``Span`` for a top-level operation, and how it can be passed down on a list of nested callbacks (always one at a time), have it as the active one for each of them, and finished **only** when the last one executes. For Python, we have decided to do it in a **fire-and-forget** fashion.
-
-Implementation details:
-
-
-* For ``threading``, the ``Span`` is manually activatted it in each corotuine/task.
-* For ``asyncio``, the active ``Span`` is not activated down the chain as the ``Context`` automatically propagates it.
-
-``threading`` implementation:
-
-.. code-block:: python
-
- def submit(self):
- span = self.tracer.scope_manager.active.span
-
- def task1():
- with self.tracer.scope_manager.activate(span, False):
- span.set_tag("key1", "1")
-
- def task2():
- with self.tracer.scope_manager.activate(span, False):
- span.set_tag("key2", "2")
- ...
-
-``asyncio`` implementation:
-
-.. code-block:: python
-
- async def task1():
- span.set_tag("key1", "1")
-
- async def task2():
- span.set_tag("key2", "2")
-
- async def task3():
- span.set_tag("key3", "3")
- span.finish()
-
- self.loop.create_task(task3())
-
- self.loop.create_task(task2())
-
- self.loop.create_task(task1())
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/test_asyncio.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/test_asyncio.py
deleted file mode 100644
index 12eb4362770..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/test_asyncio.py
+++ /dev/null
@@ -1,57 +0,0 @@
-from __future__ import print_function
-
-import asyncio
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import stop_loop_when
-
-
-class TestAsyncio(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.loop = asyncio.get_event_loop()
-
- def test_main(self):
- # Start a Span and let the callback-chain
- # finish it when the task is done
- async def task():
- with self.tracer.start_active_span("one", finish_on_close=False):
- self.submit()
-
- self.loop.create_task(task())
-
- stop_loop_when(
- self.loop,
- lambda: len(self.tracer.finished_spans()) == 1,
- timeout=5.0,
- )
- self.loop.run_forever()
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 1)
- self.assertEqual(spans[0].name, "one")
-
- for idx in range(1, 4):
- self.assertEqual(
- spans[0].attributes.get("key%s" % idx, None), str(idx)
- )
-
- def submit(self):
- span = self.tracer.scope_manager.active.span
-
- async def task1():
- span.set_tag("key1", "1")
-
- async def task2():
- span.set_tag("key2", "2")
-
- async def task3():
- span.set_tag("key3", "3")
- span.finish()
-
- self.loop.create_task(task3())
-
- self.loop.create_task(task2())
-
- self.loop.create_task(task1())
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/test_threads.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/test_threads.py
deleted file mode 100644
index a1d35c35d88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_nested_callbacks/test_threads.py
+++ /dev/null
@@ -1,59 +0,0 @@
-from __future__ import print_function
-
-from concurrent.futures import ThreadPoolExecutor
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-from ..utils import await_until
-
-
-class TestThreads(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.executor = ThreadPoolExecutor(max_workers=3)
-
- def tearDown(self):
- self.executor.shutdown(False)
-
- def test_main(self):
- # Start a Span and let the callback-chain
- # finish it when the task is done
- with self.tracer.start_active_span("one", finish_on_close=False):
- self.submit()
-
- # Cannot shutdown the executor and wait for the callbacks
- # to be run, as in such case only the first will be executed,
- # and the rest will get canceled.
- await_until(lambda: len(self.tracer.finished_spans()) == 1, 5)
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 1)
- self.assertEqual(spans[0].name, "one")
-
- for idx in range(1, 4):
- self.assertEqual(
- spans[0].attributes.get("key%s" % idx, None), str(idx)
- )
-
- def submit(self):
- span = self.tracer.scope_manager.active.span
-
- def task1():
- with self.tracer.scope_manager.activate(span, False):
- span.set_tag("key1", "1")
-
- def task2():
- with self.tracer.scope_manager.activate(span, False):
- span.set_tag("key2", "2")
-
- def task3():
- with self.tracer.scope_manager.activate(
- span, True
- ):
- span.set_tag("key3", "3")
-
- self.executor.submit(task3)
-
- self.executor.submit(task2)
-
- self.executor.submit(task1)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/README.rst b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/README.rst
deleted file mode 100644
index eaeda8e6f81..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/README.rst
+++ /dev/null
@@ -1,42 +0,0 @@
-
-Subtask Span propagation example.
-=================================
-
-This example shows an active ``Span`` being simply propagated to the subtasks -either threads or coroutines-, and finished **by** the parent task. In real-life scenarios instrumentation libraries may help with ``Span`` propagation **if** not offered by default (see implementation details below), but we show here the case without such help.
-
-Implementation details:
-
-* For ``threading``, the ``Span`` is manually passed down the call chain, activating it in each corotuine/task.
-* For ``asyncio``, the active ``Span`` is not passed nor activated down the chain as the ``Context`` automatically propagates it.
-
-``threading`` implementation:
-
-.. code-block:: python
-
- def parent_task(self, message):
- with self.tracer.start_active_span("parent") as scope:
- f = self.executor.submit(self.child_task, message, scope.span)
- res = f.result()
-
- return res
-
- def child_task(self, message, span):
- with self.tracer.scope_manager.activate(span, False):
- with self.tracer.start_active_span("child"):
- return "%s::response" % message
-
-``asyncio`` implementation:
-
-.. code-block:: python
-
- async def parent_task(self, message): # noqa
- with self.tracer.start_active_span("parent"):
- res = await self.child_task(message)
-
- return res
-
- async def child_task(self, message):
- # No need to pass/activate the parent Span, as it stays in the context.
- with self.tracer.start_active_span("child"):
- return "%s::response" % message
-
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/test_asyncio.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/test_asyncio.py
deleted file mode 100644
index 6e544560704..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/test_asyncio.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import absolute_import, print_function
-
-import asyncio
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-
-
-class TestAsyncio(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.loop = asyncio.get_event_loop()
-
- def test_main(self):
- res = self.loop.run_until_complete(self.parent_task("message"))
- self.assertEqual(res, "message::response")
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 2)
- self.assertNamesEqual(spans, ["child", "parent"])
- self.assertIsChildOf(spans[0], spans[1])
-
- async def parent_task(self, message): # noqa
- with self.tracer.start_active_span("parent"):
- res = await self.child_task(message)
-
- return res
-
- async def child_task(self, message):
- # No need to pass/activate the parent Span, as it stays in the context.
- with self.tracer.start_active_span("child"):
- return "%s::response" % message
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/test_threads.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/test_threads.py
deleted file mode 100644
index 1ba5f697cad..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/test_subtask_span_propagation/test_threads.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from __future__ import absolute_import, print_function
-
-from concurrent.futures import ThreadPoolExecutor
-
-from ..otel_ot_shim_tracer import MockTracer
-from ..testcase import OpenTelemetryTestCase
-
-
-class TestThreads(OpenTelemetryTestCase):
- def setUp(self):
- self.tracer = MockTracer()
- self.executor = ThreadPoolExecutor(max_workers=3)
-
- def test_main(self):
- res = self.executor.submit(self.parent_task, "message").result()
- self.assertEqual(res, "message::response")
-
- spans = self.tracer.finished_spans()
- self.assertEqual(len(spans), 2)
- self.assertNamesEqual(spans, ["child", "parent"])
- self.assertIsChildOf(spans[0], spans[1])
-
- def parent_task(self, message):
- with self.tracer.start_active_span("parent") as scope:
- fut = self.executor.submit(self.child_task, message, scope.span)
- res = fut.result()
-
- return res
-
- def child_task(self, message, span):
- with self.tracer.scope_manager.activate(span, False):
- with self.tracer.start_active_span("child"):
- return "%s::response" % message
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/testcase.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/testcase.py
deleted file mode 100644
index c1ce6ea5abd..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/testcase.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import unittest
-
-import opentelemetry.trace as trace_api
-
-
-# pylint: disable=C0103
-class OpenTelemetryTestCase(unittest.TestCase):
- def assertSameTrace(self, spanA, spanB):
- return self.assertEqual(spanA.context.trace_id, spanB.context.trace_id)
-
- def assertNotSameTrace(self, spanA, spanB):
- return self.assertNotEqual(
- spanA.context.trace_id, spanB.context.trace_id
- )
-
- def assertIsChildOf(self, spanA, spanB):
- # spanA is child of spanB
- self.assertIsNotNone(spanA.parent)
-
- ctxA = spanA.parent
- if isinstance(spanA.parent, trace_api.Span):
- ctxA = spanA.parent.context
-
- ctxB = spanB
- if isinstance(ctxB, trace_api.Span):
- ctxB = spanB.context
-
- return self.assertEqual(ctxA.span_id, ctxB.span_id)
-
- def assertIsNotChildOf(self, spanA, spanB):
- # spanA is NOT child of spanB
- if spanA.parent is None:
- return
-
- ctxA = spanA.parent
- if isinstance(spanA.parent, trace_api.Span):
- ctxA = spanA.parent.context
-
- ctxB = spanB
- if isinstance(ctxB, trace_api.Span):
- ctxB = spanB.context
-
- self.assertNotEqual(ctxA.span_id, ctxB.span_id)
-
- def assertNamesEqual(self, spans, names):
- self.assertEqual(list(map(lambda x: x.name, spans)), names)
diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/utils.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/utils.py
deleted file mode 100644
index a7b977f3d76..00000000000
--- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/testbed/utils.py
+++ /dev/null
@@ -1,78 +0,0 @@
-from __future__ import print_function
-
-import logging
-import threading
-import time
-
-
-class RefCount:
- """Thread-safe counter"""
-
- def __init__(self, count=1):
- self._lock = threading.Lock()
- self._count = count
-
- def incr(self):
- with self._lock:
- self._count += 1
- return self._count
-
- def decr(self):
- with self._lock:
- self._count -= 1
- return self._count
-
-
-def await_until(func, timeout=5.0):
- """Polls for func() to return True"""
- end_time = time.time() + timeout
- while time.time() < end_time and not func():
- time.sleep(0.01)
-
-
-def stop_loop_when(loop, cond_func, timeout=5.0):
- """
- Registers a periodic callback that stops the loop when cond_func() == True.
- Compatible with both Tornado and asyncio.
- """
- if cond_func() or timeout <= 0.0:
- loop.stop()
- return
-
- timeout -= 0.1
- loop.call_later(0.1, stop_loop_when, loop, cond_func, timeout)
-
-
-def get_logger(name):
- """Returns a logger with log level set to INFO"""
- logging.basicConfig(level=logging.INFO)
- return logging.getLogger(name)
-
-
-def get_one_by_tag(spans, key, value):
- """Return a single Span with a tag value/key from a list,
- errors if more than one is found."""
-
- found = []
- for span in spans:
- if span.attributes.get(key) == value:
- found.append(span)
-
- if len(found) > 1:
- raise RuntimeError("Too many values")
-
- return found[0] if len(found) > 0 else None
-
-
-def get_one_by_operation_name(spans, name):
- """Return a single Span with a name from a list,
- errors if more than one is found."""
- found = []
- for span in spans:
- if span.name == name:
- found.append(span)
-
- if len(found) > 1:
- raise RuntimeError("Too many values")
-
- return found[0] if len(found) > 0 else None
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-psycopg2/CHANGELOG.md
deleted file mode 100644
index 2aa477de2db..00000000000
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/CHANGELOG.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-psycopg2
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## 0.8b0
-
-Released 2020-05-27
-
-- Implement instrumentor interface, enabling auto-instrumentation ([#694]https://github.com/open-telemetry/opentelemetry-python/pull/694)
-
-## 0.4a0
-
-Released 2020-02-21
-
-- Initial release
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/LICENSE b/instrumentation/opentelemetry-instrumentation-psycopg2/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-psycopg2/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-psycopg2/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/README.rst b/instrumentation/opentelemetry-instrumentation-psycopg2/README.rst
deleted file mode 100644
index 3ab1025eaef..00000000000
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/README.rst
+++ /dev/null
@@ -1,20 +0,0 @@
-OpenTelemetry Psycopg Instrumentation
-=====================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-psycopg2.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-psycopg2/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-psycopg2
-
-
-References
-----------
-* `OpenTelemetry Psycopg Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/setup.cfg b/instrumentation/opentelemetry-instrumentation-psycopg2/setup.cfg
deleted file mode 100644
index db98bf1251d..00000000000
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/setup.cfg
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-psycopg2
-description = OpenTelemetry psycopg2 instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-psycopg2
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation-dbapi == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- psycopg2-binary >= 2.7.3.1
- wrapt >= 1.0.0, < 2.0.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- psycopg2 = opentelemetry.instrumentation.psycopg2:Psycopg2Instrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/setup.py b/instrumentation/opentelemetry-instrumentation-psycopg2/setup.py
deleted file mode 100644
index 4bd0e16be54..00000000000
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "psycopg2",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py b/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py
deleted file mode 100644
index 7782f6fe632..00000000000
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-The integration with PostgreSQL supports the `Psycopg`_ library, it can be enabled by
-using ``Psycopg2Instrumentor``.
-
-.. _Psycopg: http://initd.org/psycopg/
-
-Usage
------
-
-.. code-block:: python
-
- import psycopg2
- from opentelemetry import trace
- from opentelemetry.sdk.trace import TracerProvider
- from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor
-
- trace.set_tracer_provider(TracerProvider())
-
- Psycopg2Instrumentor().instrument()
-
- cnx = psycopg2.connect(database='Database')
- cursor = cnx.cursor()
- cursor.execute("INSERT INTO test (testField) VALUES (123)")
- cursor.close()
- cnx.close()
-
-API
----
-"""
-
-import psycopg2
-
-from opentelemetry.instrumentation import dbapi
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.psycopg2.version import __version__
-from opentelemetry.trace import get_tracer
-
-
-class Psycopg2Instrumentor(BaseInstrumentor):
- _CONNECTION_ATTRIBUTES = {
- "database": "info.dbname",
- "port": "info.port",
- "host": "info.host",
- "user": "info.user",
- }
-
- _DATABASE_COMPONENT = "postgresql"
- _DATABASE_TYPE = "sql"
-
- def _instrument(self, **kwargs):
- """Integrate with PostgreSQL Psycopg library.
- Psycopg: http://initd.org/psycopg/
- """
-
- tracer_provider = kwargs.get("tracer_provider")
-
- dbapi.wrap_connect(
- __name__,
- psycopg2,
- "connect",
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- version=__version__,
- tracer_provider=tracer_provider,
- )
-
- def _uninstrument(self, **kwargs):
- """"Disable Psycopg2 instrumentation"""
- dbapi.unwrap_connect(psycopg2, "connect")
-
- # pylint:disable=no-self-use
- def instrument_connection(self, connection):
- """Enable instrumentation in a Psycopg2 connection.
-
- Args:
- connection: The connection to instrument.
-
- Returns:
- An instrumented connection.
- """
- tracer = get_tracer(__name__, __version__)
-
- return dbapi.instrument_connection(
- tracer,
- connection,
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- )
-
- def uninstrument_connection(self, connection):
- """Disable instrumentation in a Psycopg2 connection.
-
- Args:
- connection: The connection to uninstrument.
-
- Returns:
- An uninstrumented connection.
- """
- return dbapi.uninstrument_connection(connection)
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/version.py b/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-psycopg2/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py b/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py
deleted file mode 100644
index cb127c7a5ef..00000000000
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py
+++ /dev/null
@@ -1,141 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest import mock
-
-import psycopg2
-
-import opentelemetry.instrumentation.psycopg2
-from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor
-from opentelemetry.sdk import resources
-from opentelemetry.test.test_base import TestBase
-
-
-class TestPostgresqlIntegration(TestBase):
- def tearDown(self):
- super().tearDown()
- with self.disable_logging():
- Psycopg2Instrumentor().uninstrument()
-
- @mock.patch("psycopg2.connect")
- # pylint: disable=unused-argument
- def test_instrumentor(self, mock_connect):
- Psycopg2Instrumentor().instrument()
-
- cnx = psycopg2.connect(database="test")
-
- cursor = cnx.cursor()
-
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.psycopg2
- )
-
- # check that no spans are generated after uninstrument
- Psycopg2Instrumentor().uninstrument()
-
- cnx = psycopg2.connect(database="test")
- cursor = cnx.cursor()
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- @mock.patch("psycopg2.connect")
- # pylint: disable=unused-argument
- def test_not_recording(self, mock_connect):
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- Psycopg2Instrumentor().instrument()
- with mock.patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- cnx = psycopg2.connect(database="test")
- cursor = cnx.cursor()
- query = "SELECT * FROM test"
- cursor.execute(query)
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- Psycopg2Instrumentor().uninstrument()
-
- @mock.patch("psycopg2.connect")
- # pylint: disable=unused-argument
- def test_custom_tracer_provider(self, mock_connect):
- resource = resources.Resource.create({})
- result = self.create_tracer_provider(resource=resource)
- tracer_provider, exporter = result
-
- Psycopg2Instrumentor().instrument(tracer_provider=tracer_provider)
-
- cnx = psycopg2.connect(database="test")
- cursor = cnx.cursor()
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- self.assertIs(span.resource, resource)
-
- @mock.patch("psycopg2.connect")
- # pylint: disable=unused-argument
- def test_instrument_connection(self, mock_connect):
- cnx = psycopg2.connect(database="test")
- query = "SELECT * FROM test"
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 0)
-
- cnx = Psycopg2Instrumentor().instrument_connection(cnx)
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- @mock.patch("psycopg2.connect")
- # pylint: disable=unused-argument
- def test_uninstrument_connection(self, mock_connect):
- Psycopg2Instrumentor().instrument()
- cnx = psycopg2.connect(database="test")
- query = "SELECT * FROM test"
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- cnx = Psycopg2Instrumentor().uninstrument_connection(cnx)
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-pymemcache/CHANGELOG.md
deleted file mode 100644
index 5cff2cb6e62..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/CHANGELOG.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-pymemcache
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## Version 0.10b0
-
-Released 2020-06-23
-
-- Initial release
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/LICENSE b/instrumentation/opentelemetry-instrumentation-pymemcache/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-pymemcache/MANIFEST.IN b/instrumentation/opentelemetry-instrumentation-pymemcache/MANIFEST.IN
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/MANIFEST.IN
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/README.rst b/instrumentation/opentelemetry-instrumentation-pymemcache/README.rst
deleted file mode 100644
index f126f4246dc..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/README.rst
+++ /dev/null
@@ -1,20 +0,0 @@
-OpenTelemetry pymemcache Instrumentation
-========================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-pymemcache.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-pymemcache/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-pymemcache
-
-
-References
-----------
-* `OpenTelemetry Pymemcache Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/setup.cfg b/instrumentation/opentelemetry-instrumentation-pymemcache/setup.cfg
deleted file mode 100644
index c352ba903c7..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/setup.cfg
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-pymemcache
-description = OpenTelemetry pymemcache instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/instrumentation/opentelemetry-instrumentation-pymemcache
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- pymemcache ~= 1.3
- wrapt >= 1.0.0, < 2.0.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- pymemcache = opentelemetry.instrumentation.pymemcache:PymemcacheInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/setup.py b/instrumentation/opentelemetry-instrumentation-pymemcache/setup.py
deleted file mode 100644
index 46bf607933b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/setup.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "pymemcache",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py b/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py
deleted file mode 100644
index a91d3b525a3..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py
+++ /dev/null
@@ -1,199 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-
-Usage
------
-
-The OpenTelemetry ``pymemcache`` integration traces pymemcache client operations
-
-Usage
------
-
-.. code-block:: python
-
- from opentelemetry import trace
- from opentelemetry.sdk.trace import TracerProvider
- from opentelemetry.instrumentation.pymemcache import PymemcacheInstrumentor
- trace.set_tracer_provider(TracerProvider())
- PymemcacheInstrumentor().instrument()
- from pymemcache.client.base import Client
- client = Client(('localhost', 11211))
- client.set('some_key', 'some_value')
-
-API
----
-"""
-# pylint: disable=no-value-for-parameter
-
-import logging
-
-import pymemcache
-from wrapt import ObjectProxy
-from wrapt import wrap_function_wrapper as _wrap
-
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.pymemcache.version import __version__
-from opentelemetry.instrumentation.utils import unwrap
-from opentelemetry.trace import SpanKind, get_tracer
-
-logger = logging.getLogger(__name__)
-
-# Network attribute semantic convention here:
-# https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/span-general.md#general-network-connection-attributes
-_HOST = "net.peer.name"
-_PORT = "net.peer.port"
-# Database semantic conventions here:
-# https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/database.md
-_DB = "db.type"
-_URL = "db.url"
-
-_DEFAULT_SERVICE = "memcached"
-_RAWCMD = "db.statement"
-_CMD = "memcached.command"
-COMMANDS = [
- "set",
- "set_many",
- "add",
- "replace",
- "append",
- "prepend",
- "cas",
- "get",
- "get_many",
- "gets",
- "gets_many",
- "delete",
- "delete_many",
- "incr",
- "decr",
- "touch",
- "stats",
- "version",
- "flush_all",
- "quit",
- "set_multi",
- "get_multi",
-]
-
-
-def _set_connection_attributes(span, instance):
- if not span.is_recording():
- return
- for key, value in _get_address_attributes(instance).items():
- span.set_attribute(key, value)
-
-
-def _with_tracer_wrapper(func):
- """Helper for providing tracer for wrapper functions."""
-
- def _with_tracer(tracer, cmd):
- def wrapper(wrapped, instance, args, kwargs):
- # prevent double wrapping
- if hasattr(wrapped, "__wrapped__"):
- return wrapped(*args, **kwargs)
-
- return func(tracer, cmd, wrapped, instance, args, kwargs)
-
- return wrapper
-
- return _with_tracer
-
-
-@_with_tracer_wrapper
-def _wrap_cmd(tracer, cmd, wrapped, instance, args, kwargs):
- with tracer.start_as_current_span(
- _CMD, kind=SpanKind.INTERNAL, attributes={}
- ) as span:
- try:
- if span.is_recording():
- if not args:
- vals = ""
- else:
- vals = _get_query_string(args[0])
-
- query = "{}{}{}".format(cmd, " " if vals else "", vals)
- span.set_attribute(_RAWCMD, query)
-
- _set_connection_attributes(span, instance)
- except Exception as ex: # pylint: disable=broad-except
- logger.warning(
- "Failed to set attributes for pymemcache span %s", str(ex)
- )
-
- return wrapped(*args, **kwargs)
-
-
-def _get_query_string(arg):
-
- """Return the query values given the first argument to a pymemcache command.
-
- If there are multiple query values, they are joined together
- space-separated.
- """
- keys = ""
-
- if isinstance(arg, dict):
- arg = list(arg)
-
- if isinstance(arg, str):
- keys = arg
- elif isinstance(arg, bytes):
- keys = arg.decode()
- elif isinstance(arg, list) and len(arg) >= 1:
- if isinstance(arg[0], str):
- keys = " ".join(arg)
- elif isinstance(arg[0], bytes):
- keys = b" ".join(arg).decode()
-
- return keys
-
-
-def _get_address_attributes(instance):
- """Attempt to get host and port from Client instance."""
- address_attributes = {}
- address_attributes[_DB] = "memcached"
-
- # client.base.Client contains server attribute which is either a host/port tuple, or unix socket path string
- # https://github.com/pinterest/pymemcache/blob/f02ddf73a28c09256589b8afbb3ee50f1171cac7/pymemcache/client/base.py#L228
- if hasattr(instance, "server"):
- if isinstance(instance.server, tuple):
- host, port = instance.server
- address_attributes[_HOST] = host
- address_attributes[_PORT] = port
- address_attributes[_URL] = "memcached://{}:{}".format(host, port)
- elif isinstance(instance.server, str):
- address_attributes[_URL] = "memcached://{}".format(instance.server)
-
- return address_attributes
-
-
-class PymemcacheInstrumentor(BaseInstrumentor):
- """An instrumentor for pymemcache See `BaseInstrumentor`"""
-
- def _instrument(self, **kwargs):
- tracer_provider = kwargs.get("tracer_provider")
- tracer = get_tracer(__name__, __version__, tracer_provider)
-
- for cmd in COMMANDS:
- _wrap(
- "pymemcache.client.base",
- "Client.{}".format(cmd),
- _wrap_cmd(tracer, cmd),
- )
-
- def _uninstrument(self, **kwargs):
- for command in COMMANDS:
- unwrap(pymemcache.client.base.Client, "{}".format(command))
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/version.py b/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-pymemcache/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py b/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py
deleted file mode 100644
index 4efb50eb4f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py
+++ /dev/null
@@ -1,541 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest import mock
-
-import pymemcache
-from pymemcache.exceptions import (
- MemcacheClientError,
- MemcacheIllegalInputError,
- MemcacheServerError,
- MemcacheUnknownCommandError,
- MemcacheUnknownError,
-)
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.pymemcache import PymemcacheInstrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace import get_tracer
-
-from .utils import MockSocket, _str
-
-TEST_HOST = "localhost"
-TEST_PORT = 117711
-
-
-class PymemcacheClientTestCase(
- TestBase
-): # pylint: disable=too-many-public-methods
- """ Tests for a patched pymemcache.client.base.Client. """
-
- def setUp(self):
- super().setUp()
- PymemcacheInstrumentor().instrument()
-
- # pylint: disable=protected-access
- self.tracer = get_tracer(__name__)
-
- def tearDown(self):
- super().tearDown()
- PymemcacheInstrumentor().uninstrument()
-
- def make_client(self, mock_socket_values, **kwargs):
- # pylint: disable=attribute-defined-outside-init
- self.client = pymemcache.client.base.Client(
- (TEST_HOST, TEST_PORT), **kwargs
- )
- self.client.sock = MockSocket(list(mock_socket_values))
- return self.client
-
- def check_spans(self, spans, num_expected, queries_expected):
- """A helper for validating basic span information."""
- self.assertEqual(num_expected, len(spans))
-
- for span, query in zip(spans, queries_expected):
- self.assertEqual(span.name, "memcached.command")
- self.assertIs(span.kind, trace_api.SpanKind.INTERNAL)
- self.assertEqual(
- span.attributes["net.peer.name"], "{}".format(TEST_HOST)
- )
- self.assertEqual(span.attributes["net.peer.port"], TEST_PORT)
- self.assertEqual(span.attributes["db.type"], "memcached")
- self.assertEqual(
- span.attributes["db.url"],
- "memcached://{}:{}".format(TEST_HOST, TEST_PORT),
- )
- self.assertEqual(span.attributes["db.statement"], query)
-
- def test_set_success(self):
- client = self.make_client([b"STORED\r\n"])
- result = client.set(b"key", b"value", noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["set key"])
-
- def test_set_not_recording(self):
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- with mock.patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- client = self.make_client([b"STORED\r\n"])
- result = client.set(b"key", b"value", noreply=False)
- self.assertTrue(result)
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_get_many_none_found(self):
- client = self.make_client([b"END\r\n"])
- result = client.get_many([b"key1", b"key2"])
- assert result == {}
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["get_many key1 key2"])
-
- def test_get_multi_none_found(self):
- client = self.make_client([b"END\r\n"])
- # alias for get_many
- result = client.get_multi([b"key1", b"key2"])
- assert result == {}
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["get_multi key1 key2"])
-
- def test_set_multi_success(self):
- client = self.make_client([b"STORED\r\n"])
- # Alias for set_many, a convienance function that calls set for every key
- result = client.set_multi({b"key": b"value"}, noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 2, ["set key", "set_multi key"])
-
- def test_delete_not_found(self):
- client = self.make_client([b"NOT_FOUND\r\n"])
- result = client.delete(b"key", noreply=False)
- assert result is False
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["delete key"])
-
- def test_incr_found(self):
- client = self.make_client([b"STORED\r\n", b"1\r\n"])
- client.set(b"key", 0, noreply=False)
- result = client.incr(b"key", 1, noreply=False)
- assert result == 1
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 2, ["set key", "incr key"])
-
- def test_get_found(self):
- client = self.make_client(
- [b"STORED\r\n", b"VALUE key 0 5\r\nvalue\r\nEND\r\n"]
- )
- result = client.set(b"key", b"value", noreply=False)
- result = client.get(b"key")
- assert result == b"value"
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 2, ["set key", "get key"])
-
- def test_decr_found(self):
- client = self.make_client([b"STORED\r\n", b"1\r\n"])
- client.set(b"key", 2, noreply=False)
- result = client.decr(b"key", 1, noreply=False)
- assert result == 1
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 2, ["set key", "decr key"])
-
- def test_add_stored(self):
- client = self.make_client([b"STORED\r", b"\n"])
- result = client.add(b"key", b"value", noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["add key"])
-
- def test_delete_many_found(self):
- client = self.make_client([b"STORED\r", b"\n", b"DELETED\r\n"])
- result = client.add(b"key", b"value", noreply=False)
- # a convienance function that calls delete for every key
- result = client.delete_many([b"key"], noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(
- spans, 3, ["add key", "delete key", "delete_many key"]
- )
-
- def test_set_many_success(self):
- client = self.make_client([b"STORED\r\n"])
- # a convienance function that calls set for every key
- result = client.set_many({b"key": b"value"}, noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 2, ["set key", "set_many key"])
-
- def test_set_get(self):
- client = self.make_client(
- [b"STORED\r\n", b"VALUE key 0 5\r\nvalue\r\nEND\r\n"]
- )
- client.set(b"key", b"value", noreply=False)
- result = client.get(b"key")
- assert _str(result) == "value"
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.assertEqual(len(spans), 2)
- self.assertEqual(
- spans[0].attributes["db.url"],
- "memcached://{}:{}".format(TEST_HOST, TEST_PORT),
- )
-
- def test_append_stored(self):
- client = self.make_client([b"STORED\r\n"])
- result = client.append(b"key", b"value", noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["append key"])
-
- def test_prepend_stored(self):
- client = self.make_client([b"STORED\r\n"])
- result = client.prepend(b"key", b"value", noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["prepend key"])
-
- def test_cas_stored(self):
- client = self.make_client([b"STORED\r\n"])
- result = client.cas(b"key", b"value", b"cas", noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["cas key"])
-
- def test_cas_exists(self):
- client = self.make_client([b"EXISTS\r\n"])
- result = client.cas(b"key", b"value", b"cas", noreply=False)
- assert result is False
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["cas key"])
-
- def test_cas_not_found(self):
- client = self.make_client([b"NOT_FOUND\r\n"])
- result = client.cas(b"key", b"value", b"cas", noreply=False)
- assert result is None
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["cas key"])
-
- def test_delete_exception(self):
- client = self.make_client([Exception("fail")])
-
- def _delete():
- client.delete(b"key", noreply=False)
-
- with self.assertRaises(Exception):
- _delete()
-
- spans = self.memory_exporter.get_finished_spans()
-
- span = spans[0]
-
- self.assertFalse(span.status.is_ok)
-
- self.check_spans(spans, 1, ["delete key"])
-
- def test_flush_all(self):
- client = self.make_client([b"OK\r\n"])
- result = client.flush_all(noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["flush_all"])
-
- def test_incr_exception(self):
- client = self.make_client([Exception("fail")])
-
- def _incr():
- client.incr(b"key", 1)
-
- with self.assertRaises(Exception):
- _incr()
-
- spans = self.memory_exporter.get_finished_spans()
-
- span = spans[0]
-
- self.assertFalse(span.status.is_ok)
-
- self.check_spans(spans, 1, ["incr key"])
-
- def test_get_error(self):
- client = self.make_client([b"ERROR\r\n"])
-
- def _get():
- client.get(b"key")
-
- with self.assertRaises(MemcacheUnknownCommandError):
- _get()
-
- spans = self.memory_exporter.get_finished_spans()
-
- span = spans[0]
-
- self.assertFalse(span.status.is_ok)
-
- self.check_spans(spans, 1, ["get key"])
-
- def test_get_unknown_error(self):
- client = self.make_client([b"foobarbaz\r\n"])
-
- def _get():
- client.get(b"key")
-
- with self.assertRaises(MemcacheUnknownError):
- _get()
-
- spans = self.memory_exporter.get_finished_spans()
-
- span = spans[0]
-
- self.assertFalse(span.status.is_ok)
-
- self.check_spans(spans, 1, ["get key"])
-
- def test_gets_found(self):
- client = self.make_client([b"VALUE key 0 5 10\r\nvalue\r\nEND\r\n"])
- result = client.gets(b"key")
- assert result == (b"value", b"10")
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["gets key"])
-
- def test_touch_not_found(self):
- client = self.make_client([b"NOT_FOUND\r\n"])
- result = client.touch(b"key", noreply=False)
- assert result is False
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["touch key"])
-
- def test_set_client_error(self):
- client = self.make_client([b"CLIENT_ERROR some message\r\n"])
-
- def _set():
- client.set("key", "value", noreply=False)
-
- with self.assertRaises(MemcacheClientError):
- _set()
-
- spans = self.memory_exporter.get_finished_spans()
-
- span = spans[0]
-
- self.assertFalse(span.status.is_ok)
-
- self.check_spans(spans, 1, ["set key"])
-
- def test_set_server_error(self):
- client = self.make_client([b"SERVER_ERROR some message\r\n"])
-
- def _set():
- client.set(b"key", b"value", noreply=False)
-
- with self.assertRaises(MemcacheServerError):
- _set()
-
- spans = self.memory_exporter.get_finished_spans()
-
- span = spans[0]
-
- self.assertFalse(span.status.is_ok)
-
- self.check_spans(spans, 1, ["set key"])
-
- def test_set_key_with_space(self):
- client = self.make_client([b""])
-
- def _set():
- client.set(b"key has space", b"value", noreply=False)
-
- with self.assertRaises(MemcacheIllegalInputError):
- _set()
-
- spans = self.memory_exporter.get_finished_spans()
-
- span = spans[0]
-
- self.assertFalse(span.status.is_ok)
-
- self.check_spans(spans, 1, ["set key has space"])
-
- def test_quit(self):
- client = self.make_client([])
- assert client.quit() is None
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["quit"])
-
- def test_replace_not_stored(self):
- client = self.make_client([b"NOT_STORED\r\n"])
- result = client.replace(b"key", b"value", noreply=False)
- assert result is False
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["replace key"])
-
- def test_version_success(self):
- client = self.make_client(
- [b"VERSION 1.2.3\r\n"], default_noreply=False
- )
- result = client.version()
- assert result == b"1.2.3"
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["version"])
-
- def test_stats(self):
- client = self.make_client([b"STAT fake_stats 1\r\n", b"END\r\n"])
- result = client.stats()
- assert client.sock.send_bufs == [b"stats \r\n"]
- assert result == {b"fake_stats": 1}
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 1, ["stats"])
-
- def test_uninstrumented(self):
- PymemcacheInstrumentor().uninstrument()
-
- client = self.make_client(
- [b"STORED\r\n", b"VALUE key 0 5\r\nvalue\r\nEND\r\n"]
- )
- client.set(b"key", b"value", noreply=False)
- result = client.get(b"key")
- assert _str(result) == "value"
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.assertEqual(len(spans), 0)
-
- PymemcacheInstrumentor().instrument()
-
-
-class PymemcacheHashClientTestCase(TestBase):
- """ Tests for a patched pymemcache.client.hash.HashClient. """
-
- def setUp(self):
- super().setUp()
- PymemcacheInstrumentor().instrument()
-
- # pylint: disable=protected-access
- self.tracer = get_tracer(__name__)
-
- def tearDown(self):
- super().tearDown()
- PymemcacheInstrumentor().uninstrument()
-
- def make_client_pool(
- self, hostname, mock_socket_values, serializer=None, **kwargs
- ): # pylint: disable=no-self-use
- mock_client = pymemcache.client.base.Client(
- hostname, serializer=serializer, **kwargs
- )
- mock_client.sock = MockSocket(mock_socket_values)
- client = pymemcache.client.base.PooledClient(
- hostname, serializer=serializer
- )
- client.client_pool = pymemcache.pool.ObjectPool(lambda: mock_client)
- return mock_client
-
- def make_client(self, *mock_socket_values, **kwargs):
- current_port = TEST_PORT
-
- # pylint: disable=import-outside-toplevel
- from pymemcache.client.hash import HashClient
-
- # pylint: disable=attribute-defined-outside-init
- self.client = HashClient([], **kwargs)
- ip = TEST_HOST
-
- for vals in mock_socket_values:
- url_string = "{}:{}".format(ip, current_port)
- clnt_pool = self.make_client_pool(
- (ip, current_port), vals, **kwargs
- )
- self.client.clients[url_string] = clnt_pool
- self.client.hasher.add_node(url_string)
- current_port += 1
- return self.client
-
- def check_spans(self, spans, num_expected, queries_expected):
- """A helper for validating basic span information."""
- self.assertEqual(num_expected, len(spans))
-
- for span, query in zip(spans, queries_expected):
- self.assertEqual(span.name, "memcached.command")
- self.assertIs(span.kind, trace_api.SpanKind.INTERNAL)
- self.assertEqual(
- span.attributes["net.peer.name"], "{}".format(TEST_HOST)
- )
- self.assertEqual(span.attributes["net.peer.port"], TEST_PORT)
- self.assertEqual(span.attributes["db.type"], "memcached")
- self.assertEqual(
- span.attributes["db.url"],
- "memcached://{}:{}".format(TEST_HOST, TEST_PORT),
- )
- self.assertEqual(span.attributes["db.statement"], query)
-
- def test_delete_many_found(self):
- client = self.make_client([b"STORED\r", b"\n", b"DELETED\r\n"])
- result = client.add(b"key", b"value", noreply=False)
- result = client.delete_many([b"key"], noreply=False)
- self.assertTrue(result)
-
- spans = self.memory_exporter.get_finished_spans()
-
- self.check_spans(spans, 2, ["add key", "delete key"])
diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/utils.py b/instrumentation/opentelemetry-instrumentation-pymemcache/tests/utils.py
deleted file mode 100644
index 361fb6e68c6..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/utils.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright The OpenTelemetry 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 collections
-import socket
-
-
-class MockSocket:
- def __init__(self, recv_bufs, connect_failure=None):
- self.recv_bufs = collections.deque(recv_bufs)
- self.send_bufs = []
- self.closed = False
- self.timeouts = []
- self.connect_failure = connect_failure
- self.connections = []
- self.socket_options = []
-
- def sendall(self, value):
- self.send_bufs.append(value)
-
- def close(self):
- self.closed = True
-
- def recv(self, size): # pylint: disable=unused-argument
- value = self.recv_bufs.popleft()
- if isinstance(value, Exception):
- raise value
- return value
-
- def settimeout(self, timeout):
- self.timeouts.append(timeout)
-
- def connect(self, server):
- if isinstance(self.connect_failure, Exception):
- raise self.connect_failure
- self.connections.append(server)
-
- def setsockopt(self, level, option, value):
- self.socket_options.append((level, option, value))
-
-
-class MockSocketModule:
- def __init__(self, connect_failure=None):
- self.connect_failure = connect_failure
- self.sockets = []
-
- def socket(self): # noqa: A002
- soket = MockSocket([], connect_failure=self.connect_failure)
- self.sockets.append(soket)
- return soket
-
- def __getattr__(self, name):
- return getattr(socket, name)
-
-
-# Compatibility to get a string back from a request
-def _str(string_input):
- if isinstance(string_input, str):
- return string_input
- if isinstance(string_input, bytes):
- return string_input.decode()
-
- return str(string_input)
diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-pymongo/CHANGELOG.md
deleted file mode 100644
index 30e36e00481..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymongo/CHANGELOG.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.14b0
-
-Released 2020-10-13
-
-- Cast PyMongo commands as strings
- ([#1132](https://github.com/open-telemetry/opentelemetry-python/pull/1132))
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-pymongo
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Implement instrumentor interface ([#612](https://github.com/open-telemetry/opentelemetry-python/pull/612))
-
-## 0.4a0
-
-Released 2020-02-21
-
-- Updating network connection attribute names
- ([#350](https://github.com/open-telemetry/opentelemetry-python/pull/350))
-
-## 0.3a0
-
-Released 2019-12-11
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/LICENSE b/instrumentation/opentelemetry-instrumentation-pymongo/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymongo/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-pymongo/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-pymongo/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymongo/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/README.rst b/instrumentation/opentelemetry-instrumentation-pymongo/README.rst
deleted file mode 100644
index 7791810e97d..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymongo/README.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-OpenTelemetry pymongo Instrumentation
-=====================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-pymongo.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-pymongo/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-pymongo
-
-
-References
-----------
-* `OpenTelemetry pymongo Instrumentation `_
-* `OpenTelemetry Project `_
-
diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/setup.cfg b/instrumentation/opentelemetry-instrumentation-pymongo/setup.cfg
deleted file mode 100644
index 6ccf6f1002e..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymongo/setup.cfg
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-pymongo
-description = OpenTelemetry pymongo instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-pymongo
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- pymongo ~= 3.1
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- pymongo = opentelemetry.instrumentation.pymongo:PymongoInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/setup.py b/instrumentation/opentelemetry-instrumentation-pymongo/setup.py
deleted file mode 100644
index 7b862ae2aa8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymongo/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "pymongo",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py b/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py
deleted file mode 100644
index adc51b1c847..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py
+++ /dev/null
@@ -1,169 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-The integration with MongoDB supports the `pymongo`_ library, it can be
-enabled using the ``PymongoInstrumentor``.
-
-.. _pymongo: https://pypi.org/project/pymongo
-
-Usage
------
-
-.. code:: python
-
- from pymongo import MongoClient
- from opentelemetry import trace
- from opentelemetry.trace import TracerProvider
- from opentelemetry.instrumentation.pymongo import PymongoInstrumentor
-
- trace.set_tracer_provider(TracerProvider())
-
- PymongoInstrumentor().instrument()
- client = MongoClient()
- db = client["MongoDB_Database"]
- collection = db["MongoDB_Collection"]
- collection.find_one()
-
-API
----
-"""
-
-from pymongo import monitoring
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.pymongo.version import __version__
-from opentelemetry.trace import SpanKind, get_tracer
-from opentelemetry.trace.status import Status, StatusCode
-
-DATABASE_TYPE = "mongodb"
-COMMAND_ATTRIBUTES = ["filter", "sort", "skip", "limit", "pipeline"]
-
-
-class CommandTracer(monitoring.CommandListener):
- def __init__(self, tracer):
- self._tracer = tracer
- self._span_dict = {}
- self.is_enabled = True
-
- def started(self, event: monitoring.CommandStartedEvent):
- """ Method to handle a pymongo CommandStartedEvent """
- if not self.is_enabled:
- return
- command = event.command.get(event.command_name, "")
- name = DATABASE_TYPE + "." + event.command_name
- statement = event.command_name
- if command:
- name += "." + str(command)
- statement += " " + str(command)
-
- try:
- span = self._tracer.start_span(name, kind=SpanKind.CLIENT)
- if span.is_recording():
- span.set_attribute("component", DATABASE_TYPE)
- span.set_attribute("db.type", DATABASE_TYPE)
- span.set_attribute("db.instance", event.database_name)
- span.set_attribute("db.statement", statement)
- if event.connection_id is not None:
- span.set_attribute("net.peer.name", event.connection_id[0])
- span.set_attribute("net.peer.port", event.connection_id[1])
-
- # pymongo specific, not specified by spec
- span.set_attribute("db.mongo.operation_id", event.operation_id)
- span.set_attribute("db.mongo.request_id", event.request_id)
-
- for attr in COMMAND_ATTRIBUTES:
- _attr = event.command.get(attr)
- if _attr is not None:
- span.set_attribute("db.mongo." + attr, str(_attr))
-
- # Add Span to dictionary
- self._span_dict[_get_span_dict_key(event)] = span
- except Exception as ex: # noqa pylint: disable=broad-except
- if span is not None and span.is_recording():
- span.set_status(Status(StatusCode.ERROR, str(ex)))
- span.end()
- self._pop_span(event)
-
- def succeeded(self, event: monitoring.CommandSucceededEvent):
- """ Method to handle a pymongo CommandSucceededEvent """
- if not self.is_enabled:
- return
- span = self._pop_span(event)
- if span is None:
- return
- if span.is_recording():
- span.set_attribute(
- "db.mongo.duration_micros", event.duration_micros
- )
- span.end()
-
- def failed(self, event: monitoring.CommandFailedEvent):
- """ Method to handle a pymongo CommandFailedEvent """
- if not self.is_enabled:
- return
- span = self._pop_span(event)
- if span is None:
- return
- if span.is_recording():
- span.set_attribute(
- "db.mongo.duration_micros", event.duration_micros
- )
- span.set_status(Status(StatusCode.ERROR, event.failure))
- span.end()
-
- def _pop_span(self, event):
- return self._span_dict.pop(_get_span_dict_key(event), None)
-
-
-def _get_span_dict_key(event):
- if event.connection_id is not None:
- return (event.request_id, event.connection_id)
- return event.request_id
-
-
-class PymongoInstrumentor(BaseInstrumentor):
- _commandtracer_instance = None # type CommandTracer
- # The instrumentation for PyMongo is based on the event listener interface
- # https://api.mongodb.com/python/current/api/pymongo/monitoring.html.
- # This interface only allows to register listeners and does not provide
- # an unregister API. In order to provide a mechanishm to disable
- # instrumentation an enabled flag is implemented in CommandTracer,
- # it's checked in the different listeners.
-
- def _instrument(self, **kwargs):
- """Integrate with pymongo to trace it using event listener.
- https://api.mongodb.com/python/current/api/pymongo/monitoring.html
-
- Args:
- tracer_provider: The `TracerProvider` to use. If none is passed the
- current configured one is used.
- """
-
- tracer_provider = kwargs.get("tracer_provider")
-
- # Create and register a CommandTracer only the first time
- if self._commandtracer_instance is None:
- tracer = get_tracer(__name__, __version__, tracer_provider)
-
- self._commandtracer_instance = CommandTracer(tracer)
- monitoring.register(self._commandtracer_instance)
-
- # If already created, just enable it
- self._commandtracer_instance.is_enabled = True
-
- def _uninstrument(self, **kwargs):
- if self._commandtracer_instance is not None:
- self._commandtracer_instance.is_enabled = False
diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/version.py b/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-pymongo/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py b/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py
deleted file mode 100644
index a3bb7b2223c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest import mock
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.pymongo import (
- CommandTracer,
- PymongoInstrumentor,
-)
-from opentelemetry.test.test_base import TestBase
-
-
-class TestPymongo(TestBase):
- def setUp(self):
- super().setUp()
- self.tracer = self.tracer_provider.get_tracer(__name__)
-
- def test_pymongo_instrumentor(self):
- mock_register = mock.Mock()
- patch = mock.patch(
- "pymongo.monitoring.register", side_effect=mock_register
- )
- with patch:
- PymongoInstrumentor().instrument()
-
- self.assertTrue(mock_register.called)
-
- def test_started(self):
- command_attrs = {
- "filter": "filter",
- "sort": "sort",
- "limit": "limit",
- "pipeline": "pipeline",
- "command_name": "find",
- }
- command_tracer = CommandTracer(self.tracer)
- mock_event = MockEvent(
- command_attrs, ("test.com", "1234"), "test_request_id"
- )
- command_tracer.started(event=mock_event)
- # the memory exporter can't be used here because the span isn't ended
- # yet
- # pylint: disable=protected-access
- span = command_tracer._pop_span(mock_event)
- self.assertIs(span.kind, trace_api.SpanKind.CLIENT)
- self.assertEqual(span.name, "mongodb.command_name.find")
- self.assertEqual(span.attributes["component"], "mongodb")
- self.assertEqual(span.attributes["db.type"], "mongodb")
- self.assertEqual(span.attributes["db.instance"], "database_name")
- self.assertEqual(span.attributes["db.statement"], "command_name find")
- self.assertEqual(span.attributes["net.peer.name"], "test.com")
- self.assertEqual(span.attributes["net.peer.port"], "1234")
- self.assertEqual(
- span.attributes["db.mongo.operation_id"], "operation_id"
- )
- self.assertEqual(
- span.attributes["db.mongo.request_id"], "test_request_id"
- )
-
- self.assertEqual(span.attributes["db.mongo.filter"], "filter")
- self.assertEqual(span.attributes["db.mongo.sort"], "sort")
- self.assertEqual(span.attributes["db.mongo.limit"], "limit")
- self.assertEqual(span.attributes["db.mongo.pipeline"], "pipeline")
-
- def test_succeeded(self):
- mock_event = MockEvent({})
- command_tracer = CommandTracer(self.tracer)
- command_tracer.started(event=mock_event)
- command_tracer.succeeded(event=mock_event)
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
- self.assertEqual(
- span.attributes["db.mongo.duration_micros"], "duration_micros"
- )
- self.assertIs(
- span.status.status_code, trace_api.status.StatusCode.UNSET
- )
- self.assertIsNotNone(span.end_time)
-
- def test_not_recording(self):
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- mock_event = MockEvent({})
- command_tracer = CommandTracer(mock_tracer)
- command_tracer.started(event=mock_event)
- command_tracer.succeeded(event=mock_event)
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_failed(self):
- mock_event = MockEvent({})
- command_tracer = CommandTracer(self.tracer)
- command_tracer.started(event=mock_event)
- command_tracer.failed(event=mock_event)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- self.assertEqual(
- span.attributes["db.mongo.duration_micros"], "duration_micros"
- )
- self.assertIs(
- span.status.status_code, trace_api.status.StatusCode.ERROR,
- )
- self.assertEqual(span.status.description, "failure")
- self.assertIsNotNone(span.end_time)
-
- def test_multiple_commands(self):
- first_mock_event = MockEvent({}, ("firstUrl", "123"), "first")
- second_mock_event = MockEvent({}, ("secondUrl", "456"), "second")
- command_tracer = CommandTracer(self.tracer)
- command_tracer.started(event=first_mock_event)
- command_tracer.started(event=second_mock_event)
- command_tracer.succeeded(event=first_mock_event)
- command_tracer.failed(event=second_mock_event)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 2)
- first_span = spans_list[0]
- second_span = spans_list[1]
-
- self.assertEqual(first_span.attributes["db.mongo.request_id"], "first")
- self.assertIs(
- first_span.status.status_code, trace_api.status.StatusCode.UNSET,
- )
- self.assertEqual(
- second_span.attributes["db.mongo.request_id"], "second"
- )
- self.assertIs(
- second_span.status.status_code, trace_api.status.StatusCode.ERROR,
- )
-
- def test_int_command(self):
- command_attrs = {
- "command_name": 123,
- }
- mock_event = MockEvent(command_attrs)
-
- command_tracer = CommandTracer(self.tracer)
- command_tracer.started(event=mock_event)
- command_tracer.succeeded(event=mock_event)
-
- spans_list = self.memory_exporter.get_finished_spans()
-
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- self.assertEqual(span.name, "mongodb.command_name.123")
-
-
-class MockCommand:
- def __init__(self, command_attrs):
- self.command_attrs = command_attrs
-
- def get(self, key, default=""):
- return self.command_attrs.get(key, default)
-
-
-class MockEvent:
- def __init__(self, command_attrs, connection_id=None, request_id=""):
- self.command = MockCommand(command_attrs)
- self.connection_id = connection_id
- self.request_id = request_id
-
- def __getattr__(self, item):
- return item
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-pymysql/CHANGELOG.md
deleted file mode 100644
index 3f78db57b96..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymysql/CHANGELOG.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.14b0
-
-Released 2020-10-13
-
-- Bumped version from 0.9.3 to 0.10.1
- ([#1228](https://github.com/open-telemetry/opentelemetry-python/pull/1228))
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-pymysql
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Initial release
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/README.rst b/instrumentation/opentelemetry-instrumentation-pymysql/README.rst
deleted file mode 100644
index 0b566d2a94c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymysql/README.rst
+++ /dev/null
@@ -1,20 +0,0 @@
-OpenTelemetry PyMySQL Instrumentation
-=====================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-pymysql.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-pymysql/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-pymysql
-
-
-References
-----------
-* `OpenTelemetry PyMySQL Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/setup.cfg b/instrumentation/opentelemetry-instrumentation-pymysql/setup.cfg
deleted file mode 100644
index b84fe20d555..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymysql/setup.cfg
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-pymysql
-description = OpenTelemetry PyMySQL instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-pymysql
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation-dbapi == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- PyMySQL ~= 0.10.1
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- pymysql = opentelemetry.instrumentation.pymysql:PyMySQLInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/setup.py b/instrumentation/opentelemetry-instrumentation-pymysql/setup.py
deleted file mode 100644
index 74cd948fee8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymysql/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "pymysql",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py
deleted file mode 100644
index 5d299505d69..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-The integration with PyMySQL supports the `PyMySQL`_ library and can be enabled
-by using ``PyMySQLInstrumentor``.
-
-.. _PyMySQL: https://pypi.org/project/PyMySQL/
-
-Usage
------
-
-.. code:: python
-
- import pymysql
- from opentelemetry import trace
- from opentelemetry.instrumentation.pymysql import PyMySQLInstrumentor
- from opentelemetry.sdk.trace import TracerProvider
-
- trace.set_tracer_provider(TracerProvider())
-
- PyMySQLInstrumentor().instrument()
-
- cnx = pymysql.connect(database="MySQL_Database")
- cursor = cnx.cursor()
- cursor.execute("INSERT INTO test (testField) VALUES (123)"
- cnx.commit()
- cursor.close()
- cnx.close()
-
-API
----
-"""
-
-import pymysql
-
-from opentelemetry.instrumentation import dbapi
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.pymysql.version import __version__
-
-
-class PyMySQLInstrumentor(BaseInstrumentor):
- _CONNECTION_ATTRIBUTES = {
- "database": "db",
- "port": "port",
- "host": "host",
- "user": "user",
- }
-
- _DATABASE_COMPONENT = "mysql"
- _DATABASE_TYPE = "sql"
-
- def _instrument(self, **kwargs):
- """Integrate with the PyMySQL library.
- https://github.com/PyMySQL/PyMySQL/
- """
- tracer_provider = kwargs.get("tracer_provider")
-
- dbapi.wrap_connect(
- __name__,
- pymysql,
- "connect",
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- version=__version__,
- tracer_provider=tracer_provider,
- )
-
- def _uninstrument(self, **kwargs):
- """"Disable PyMySQL instrumentation"""
- dbapi.unwrap_connect(pymysql, "connect")
-
- # pylint:disable=no-self-use
- def instrument_connection(self, connection):
- """Enable instrumentation in a PyMySQL connection.
-
- Args:
- connection: The connection to instrument.
-
- Returns:
- An instrumented connection.
- """
-
- return dbapi.instrument_connection(
- __name__,
- connection,
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- version=__version__,
- )
-
- def uninstrument_connection(self, connection):
- """Disable instrumentation in a PyMySQL connection.
-
- Args:
- connection: The connection to uninstrument.
-
- Returns:
- An uninstrumented connection.
- """
- return dbapi.uninstrument_connection(connection)
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/version.py b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-pymysql/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/tests/test_pymysql_integration.py b/instrumentation/opentelemetry-instrumentation-pymysql/tests/test_pymysql_integration.py
deleted file mode 100644
index 35c9f4d32b6..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pymysql/tests/test_pymysql_integration.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest import mock
-
-import pymysql
-
-import opentelemetry.instrumentation.pymysql
-from opentelemetry.instrumentation.pymysql import PyMySQLInstrumentor
-from opentelemetry.sdk import resources
-from opentelemetry.test.test_base import TestBase
-
-
-class TestPyMysqlIntegration(TestBase):
- def tearDown(self):
- super().tearDown()
- with self.disable_logging():
- PyMySQLInstrumentor().uninstrument()
-
- @mock.patch("pymysql.connect")
- # pylint: disable=unused-argument
- def test_instrumentor(self, mock_connect):
- PyMySQLInstrumentor().instrument()
-
- cnx = pymysql.connect(database="test")
- cursor = cnx.cursor()
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- # Check version and name in span's instrumentation info
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.pymysql
- )
-
- # check that no spans are generated after uninstrument
- PyMySQLInstrumentor().uninstrument()
-
- cnx = pymysql.connect(database="test")
- cursor = cnx.cursor()
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- @mock.patch("pymysql.connect")
- # pylint: disable=unused-argument
- def test_custom_tracer_provider(self, mock_connect):
- resource = resources.Resource.create({})
- result = self.create_tracer_provider(resource=resource)
- tracer_provider, exporter = result
-
- PyMySQLInstrumentor().instrument(tracer_provider=tracer_provider)
-
- cnx = pymysql.connect(database="test")
- cursor = cnx.cursor()
- query = "SELECT * FROM test"
- cursor.execute(query)
-
- spans_list = exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
- span = spans_list[0]
-
- self.assertIs(span.resource, resource)
-
- @mock.patch("pymysql.connect")
- # pylint: disable=unused-argument
- def test_instrument_connection(self, mock_connect):
- cnx = pymysql.connect(database="test")
- query = "SELECT * FROM test"
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 0)
-
- cnx = PyMySQLInstrumentor().instrument_connection(cnx)
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- @mock.patch("pymysql.connect")
- # pylint: disable=unused-argument
- def test_uninstrument_connection(self, mock_connect):
- PyMySQLInstrumentor().instrument()
- cnx = pymysql.connect(database="test")
- query = "SELECT * FROM test"
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
-
- cnx = PyMySQLInstrumentor().uninstrument_connection(cnx)
- cursor = cnx.cursor()
- cursor.execute(query)
-
- spans_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans_list), 1)
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-pyramid/CHANGELOG.md
deleted file mode 100644
index 6f78bfc16ae..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/CHANGELOG.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-pyramid ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-- Update environment variable names, prefix changed from `OPENTELEMETRY` to `OTEL` ([#904](https://github.com/open-telemetry/opentelemetry-python/pull/904))
-
-## Version 0.11b0
-
-- Use one general exclude list instead of two ([#872](https://github.com/open-telemetry/opentelemetry-python/pull/872))
-
-## 0.9b0
-
-Released 2020-06-10
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/LICENSE b/instrumentation/opentelemetry-instrumentation-pyramid/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-pyramid/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-pyramid/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/README.rst b/instrumentation/opentelemetry-instrumentation-pyramid/README.rst
deleted file mode 100644
index 931486773ae..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/README.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-OpenTelemetry Pyramid Instrumentation
-=====================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-pyramid.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-pyramid/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-pyramid
-
-Exclude lists
-*************
-To exclude certain URLs from being tracked, set the environment variable ``OTEL_PYTHON_PYRAMID_EXCLUDED_URLS`` with comma delimited regexes representing which URLs to exclude.
-
-For example,
-
-::
-
- export OTEL_PYTHON_PYRAMID_EXCLUDED_URLS="client/.*/info,healthcheck"
-
-will exclude requests such as ``https://site/client/123/info`` and ``https://site/xyz/healthcheck``.
-
-References
-----------
-* `OpenTelemetry Pyramid Instrumentation `_
-* `OpenTelemetry Project `_
-
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg b/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg
deleted file mode 100644
index 44db6be9610..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-pyramid
-description = OpenTelemetry Pyramid instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-pyramid
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- pyramid >= 1.7
- opentelemetry-instrumentation == 0.16.dev0
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation-wsgi == 0.16.dev0
- wrapt >= 1.0.0, < 2.0.0
-
-[options.extras_require]
-test =
- werkzeug == 0.16.1
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- pyramid = opentelemetry.instrumentation.pyramid:PyramidInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/setup.py b/instrumentation/opentelemetry-instrumentation-pyramid/setup.py
deleted file mode 100644
index 7141a898132..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "pyramid",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/__init__.py b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/__init__.py
deleted file mode 100644
index 4125453153b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/__init__.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-Pyramid instrumentation supporting `pyramid`_, it can be enabled by
-using ``PyramidInstrumentor``.
-
-.. _pyramid: https://docs.pylonsproject.org/projects/pyramid/en/latest/
-
-Usage
------
-There are two methods to instrument Pyramid:
-
-Method 1 (Instrument all Configurators):
-----------------------------------------
-
-.. code:: python
-
- from pyramid.config import Configurator
- from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
-
- PyramidInstrumentor().instrument()
-
- config = Configurator()
-
- # use your config as normal
- config.add_route('index', '/')
-
-Method 2 (Instrument one Configurator):
----------------------------------------
-
-.. code:: python
-
- from pyramid.config import Configurator
- from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
-
- config = Configurator()
- PyramidInstrumentor().instrument_config(config)
-
- # use your config as normal
- config.add_route('index', '/')
-
-Using ``pyramid.tweens`` setting:
----------------------------------
-
-If you use Method 2 and then set tweens for your application with the ``pyramid.tweens`` setting,
-you need to add ``opentelemetry.instrumentation.pyramid.trace_tween_factory`` explicity to the list,
-*as well as* instrumenting the config as shown above.
-
-For example:
-
-.. code:: python
-
- from pyramid.config import Configurator
- from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
-
- settings = {
- 'pyramid.tweens', 'opentelemetry.instrumentation.pyramid.trace_tween_factory\\nyour_tween_no_1\\nyour_tween_no_2',
- }
- config = Configurator(settings=settings)
- PyramidInstrumentor().instrument_config(config)
-
- # use your config as normal.
- config.add_route('index', '/')
-
-API
----
-"""
-
-import typing
-
-from pyramid.config import Configurator
-from pyramid.path import caller_package
-from pyramid.settings import aslist
-from wrapt import ObjectProxy
-from wrapt import wrap_function_wrapper as _wrap
-
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.pyramid.callbacks import (
- SETTING_TRACE_ENABLED,
- TWEEN_NAME,
- trace_tween_factory,
-)
-from opentelemetry.instrumentation.pyramid.version import __version__
-from opentelemetry.instrumentation.utils import unwrap
-from opentelemetry.trace import TracerProvider, get_tracer
-
-
-def _traced_init(wrapped, instance, args, kwargs):
- settings = kwargs.get("settings", {})
- tweens = aslist(settings.get("pyramid.tweens", []))
-
- if tweens and TWEEN_NAME not in settings:
- # pyramid.tweens.EXCVIEW is the name of built-in exception view provided by
- # pyramid. We need our tween to be before it, otherwise unhandled
- # exceptions will be caught before they reach our tween.
- tweens = [TWEEN_NAME] + tweens
-
- settings["pyramid.tweens"] = "\n".join(tweens)
-
- kwargs["settings"] = settings
-
- # `caller_package` works by walking a fixed amount of frames up the stack
- # to find the calling package. So if we let the original `__init__`
- # function call it, our wrapper will mess things up.
- if not kwargs.get("package", None):
- # Get the package for the third frame up from this one.
- # Default is `level=2` which will give us the package from `wrapt`
- # instead of the desired package (the caller)
- kwargs["package"] = caller_package(level=3)
-
- wrapped(*args, **kwargs)
- instance.include("opentelemetry.instrumentation.pyramid.callbacks")
-
-
-class PyramidInstrumentor(BaseInstrumentor):
- def _instrument(self, **kwargs):
- """Integrate with Pyramid Python library.
- https://docs.pylonsproject.org/projects/pyramid/en/latest/
- """
- _wrap("pyramid.config", "Configurator.__init__", _traced_init)
-
- def _uninstrument(self, **kwargs):
- """"Disable Pyramid instrumentation"""
- unwrap(Configurator, "__init__")
-
- # pylint:disable=no-self-use
- def instrument_config(self, config):
- """Enable instrumentation in a Pyramid configurator.
-
- Args:
- config: The Configurator to instrument.
- """
- config.include("opentelemetry.instrumentation.pyramid.callbacks")
-
- def uninstrument_config(self, config):
- config.add_settings({SETTING_TRACE_ENABLED: False})
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py
deleted file mode 100644
index e7110bd2b55..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py
+++ /dev/null
@@ -1,165 +0,0 @@
-from logging import getLogger
-
-from pyramid.events import BeforeTraversal
-from pyramid.httpexceptions import HTTPException
-from pyramid.settings import asbool
-from pyramid.tweens import EXCVIEW
-
-import opentelemetry.instrumentation.wsgi as otel_wsgi
-from opentelemetry import configuration, context, propagators, trace
-from opentelemetry.instrumentation.pyramid.version import __version__
-from opentelemetry.util import ExcludeList, time_ns
-
-TWEEN_NAME = "opentelemetry.instrumentation.pyramid.trace_tween_factory"
-SETTING_TRACE_ENABLED = "opentelemetry-pyramid.trace_enabled"
-
-_ENVIRON_STARTTIME_KEY = "opentelemetry-pyramid.starttime_key"
-_ENVIRON_SPAN_KEY = "opentelemetry-pyramid.span_key"
-_ENVIRON_ACTIVATION_KEY = "opentelemetry-pyramid.activation_key"
-_ENVIRON_ENABLED_KEY = "opentelemetry-pyramid.tracing_enabled_key"
-_ENVIRON_TOKEN = "opentelemetry-pyramid.token"
-
-_logger = getLogger(__name__)
-
-
-def get_excluded_urls():
- urls = configuration.Configuration().PYRAMID_EXCLUDED_URLS or []
- if urls:
- urls = str.split(urls, ",")
- return ExcludeList(urls)
-
-
-_excluded_urls = get_excluded_urls()
-
-
-def includeme(config):
- config.add_settings({SETTING_TRACE_ENABLED: True})
-
- config.add_subscriber(_before_traversal, BeforeTraversal)
- _insert_tween(config)
-
-
-def _insert_tween(config):
- settings = config.get_settings()
- tweens = settings.get("pyramid.tweens")
- # If the list is empty, pyramid does not consider the tweens have been
- # set explicitly. And if our tween is already there, nothing to do
- if not tweens or not tweens.strip():
- # Add our tween just before the default exception handler
- config.add_tween(TWEEN_NAME, over=EXCVIEW)
-
-
-def _before_traversal(event):
- request = event.request
- environ = request.environ
- span_name = otel_wsgi.get_default_span_name(environ)
-
- enabled = environ.get(_ENVIRON_ENABLED_KEY)
- if enabled is None:
- _logger.warning(
- "Opentelemetry pyramid tween 'opentelemetry.instrumentation.pyramid.trace_tween_factory'"
- "was not called. Make sure that the tween is included in 'pyramid.tweens' if"
- "the tween list was created manually"
- )
- return
-
- if not enabled:
- # Tracing not enabled, return
- return
-
- start_time = environ.get(_ENVIRON_STARTTIME_KEY)
-
- token = context.attach(
- propagators.extract(otel_wsgi.carrier_getter, environ)
- )
- tracer = trace.get_tracer(__name__, __version__)
-
- if request.matched_route:
- span_name = request.matched_route.pattern
- else:
- span_name = otel_wsgi.get_default_span_name(environ)
-
- span = tracer.start_span(
- span_name, kind=trace.SpanKind.SERVER, start_time=start_time,
- )
-
- if span.is_recording():
- attributes = otel_wsgi.collect_request_attributes(environ)
- if request.matched_route:
- attributes["http.route"] = request.matched_route.pattern
- for key, value in attributes.items():
- span.set_attribute(key, value)
-
- activation = tracer.use_span(span, end_on_exit=True)
- activation.__enter__()
- environ[_ENVIRON_ACTIVATION_KEY] = activation
- environ[_ENVIRON_SPAN_KEY] = span
- environ[_ENVIRON_TOKEN] = token
-
-
-def trace_tween_factory(handler, registry):
- settings = registry.settings
- enabled = asbool(settings.get(SETTING_TRACE_ENABLED, True))
-
- if not enabled:
- # If disabled, make a tween that signals to the
- # BeforeTraversal subscriber that tracing is disabled
- def disabled_tween(request):
- request.environ[_ENVIRON_ENABLED_KEY] = False
- return handler(request)
-
- return disabled_tween
-
- # make a request tracing function
- def trace_tween(request):
- if _excluded_urls.url_disabled(request.url):
- request.environ[_ENVIRON_ENABLED_KEY] = False
- # short-circuit when we don't want to trace anything
- return handler(request)
-
- request.environ[_ENVIRON_ENABLED_KEY] = True
- request.environ[_ENVIRON_STARTTIME_KEY] = time_ns()
-
- try:
- response = handler(request)
- response_or_exception = response
- except HTTPException as exc:
- # If the exception is a pyramid HTTPException,
- # that's still valuable information that isn't necessarily
- # a 500. For instance, HTTPFound is a 302.
- # As described in docs, Pyramid exceptions are all valid
- # response types
- response_or_exception = exc
- raise
- finally:
- span = request.environ.get(_ENVIRON_SPAN_KEY)
- enabled = request.environ.get(_ENVIRON_ENABLED_KEY)
- if not span and enabled:
- _logger.warning(
- "Pyramid environ's OpenTelemetry span missing."
- "If the OpenTelemetry tween was added manually, make sure"
- "PyramidInstrumentor().instrument_config(config) is called"
- )
- elif enabled:
- otel_wsgi.add_response_attributes(
- span,
- response_or_exception.status,
- response_or_exception.headers,
- )
-
- activation = request.environ.get(_ENVIRON_ACTIVATION_KEY)
-
- if isinstance(response_or_exception, HTTPException):
- activation.__exit__(
- type(response_or_exception),
- response_or_exception,
- getattr(response_or_exception, "__traceback__", None),
- )
- else:
- activation.__exit__(None, None, None)
-
- context.detach(request.environ.get(_ENVIRON_TOKEN))
-
- return response
-
- return trace_tween
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/version.py b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/pyramid_base_test.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/pyramid_base_test.py
deleted file mode 100644
index 21a6a1ab95e..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/tests/pyramid_base_test.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright The OpenTelemetry 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 pyramid.httpexceptions as exc
-from pyramid.response import Response
-from werkzeug.test import Client
-from werkzeug.wrappers import BaseResponse
-
-from opentelemetry.configuration import Configuration
-
-
-class InstrumentationTest:
- def setUp(self): # pylint: disable=invalid-name
- super().setUp() # pylint: disable=no-member
- Configuration._reset() # pylint: disable=protected-access
-
- @staticmethod
- def _hello_endpoint(request):
- helloid = int(request.matchdict["helloid"])
- if helloid == 500:
- raise exc.HTTPInternalServerError()
- return Response("Hello: " + str(helloid))
-
- def _common_initialization(self, config):
- # pylint: disable=unused-argument
- def excluded_endpoint(request):
- return Response("excluded")
-
- # pylint: disable=unused-argument
- def excluded2_endpoint(request):
- return Response("excluded2")
-
- config.add_route("hello", "/hello/{helloid}")
- config.add_view(self._hello_endpoint, route_name="hello")
- config.add_route("excluded_arg", "/excluded/{helloid}")
- config.add_view(self._hello_endpoint, route_name="excluded_arg")
- config.add_route("excluded", "/excluded_noarg")
- config.add_view(excluded_endpoint, route_name="excluded")
- config.add_route("excluded2", "/excluded_noarg2")
- config.add_view(excluded2_endpoint, route_name="excluded2")
-
- # pylint: disable=attribute-defined-outside-init
- self.client = Client(config.make_wsgi_app(), BaseResponse)
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_automatic.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_automatic.py
deleted file mode 100644
index b065e260648..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_automatic.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright The OpenTelemetry 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 pyramid.config import Configurator
-
-from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.test.wsgitestutil import WsgiTestBase
-
-# pylint: disable=import-error
-from .pyramid_base_test import InstrumentationTest
-
-
-class TestAutomatic(InstrumentationTest, TestBase, WsgiTestBase):
- def setUp(self):
- super().setUp()
-
- PyramidInstrumentor().instrument()
-
- self.config = Configurator()
-
- self._common_initialization(self.config)
-
- def tearDown(self):
- super().tearDown()
- with self.disable_logging():
- PyramidInstrumentor().uninstrument()
-
- def test_uninstrument(self):
- # pylint: disable=access-member-before-definition
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- PyramidInstrumentor().uninstrument()
- self.config = Configurator()
-
- self._common_initialization(self.config)
-
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- def test_tween_list(self):
- tween_list = "pyramid.tweens.excview_tween_factory"
- config = Configurator(settings={"pyramid.tweens": tween_list})
- self._common_initialization(config)
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- PyramidInstrumentor().uninstrument()
-
- self.config = Configurator()
-
- self._common_initialization(self.config)
-
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py
deleted file mode 100644
index 77427b0db7a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py
+++ /dev/null
@@ -1,209 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest.mock import Mock, patch
-
-from pyramid.config import Configurator
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.test.wsgitestutil import WsgiTestBase
-from opentelemetry.util import ExcludeList
-
-# pylint: disable=import-error
-from .pyramid_base_test import InstrumentationTest
-
-
-def expected_attributes(override_attributes):
- default_attributes = {
- "component": "http",
- "http.method": "GET",
- "http.server_name": "localhost",
- "http.scheme": "http",
- "host.port": 80,
- "http.host": "localhost",
- "http.target": "/",
- "http.flavor": "1.1",
- "http.status_text": "OK",
- "http.status_code": 200,
- }
- for key, val in override_attributes.items():
- default_attributes[key] = val
- return default_attributes
-
-
-class TestProgrammatic(InstrumentationTest, TestBase, WsgiTestBase):
- def setUp(self):
- super().setUp()
- config = Configurator()
- PyramidInstrumentor().instrument_config(config)
-
- self.config = config
-
- self._common_initialization(self.config)
-
- def tearDown(self):
- super().tearDown()
- with self.disable_logging():
- PyramidInstrumentor().uninstrument_config(self.config)
-
- def test_uninstrument(self):
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- PyramidInstrumentor().uninstrument_config(self.config)
- # Need to remake the WSGI app export
- self._common_initialization(self.config)
-
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- def test_simple(self):
- expected_attrs = expected_attributes(
- {"http.target": "/hello/123", "http.route": "/hello/{helloid}"}
- )
- self.client.get("/hello/123")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
- self.assertEqual(span_list[0].name, "/hello/{helloid}")
- self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
- self.assertEqual(span_list[0].attributes, expected_attrs)
-
- def test_not_recording(self):
- mock_tracer = Mock()
- mock_span = Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- with patch("opentelemetry.trace.get_tracer"):
- self.client.get("/hello/123")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 0)
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_404(self):
- expected_attrs = expected_attributes(
- {
- "http.method": "POST",
- "http.target": "/bye",
- "http.status_text": "Not Found",
- "http.status_code": 404,
- }
- )
-
- resp = self.client.post("/bye")
- self.assertEqual(404, resp.status_code)
- resp.close()
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
- self.assertEqual(span_list[0].name, "HTTP POST")
- self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
- self.assertEqual(span_list[0].attributes, expected_attrs)
-
- def test_internal_error(self):
- expected_attrs = expected_attributes(
- {
- "http.target": "/hello/500",
- "http.route": "/hello/{helloid}",
- "http.status_text": "Internal Server Error",
- "http.status_code": 500,
- }
- )
- resp = self.client.get("/hello/500")
- self.assertEqual(500, resp.status_code)
- resp.close()
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
- self.assertEqual(span_list[0].name, "/hello/{helloid}")
- self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
- self.assertEqual(span_list[0].attributes, expected_attrs)
-
- def test_tween_list(self):
- tween_list = "opentelemetry.instrumentation.pyramid.trace_tween_factory\npyramid.tweens.excview_tween_factory"
- config = Configurator(settings={"pyramid.tweens": tween_list})
- PyramidInstrumentor().instrument_config(config)
- self._common_initialization(config)
-
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- PyramidInstrumentor().uninstrument_config(config)
- # Need to remake the WSGI app export
- self._common_initialization(config)
-
- resp = self.client.get("/hello/123")
- self.assertEqual(200, resp.status_code)
- self.assertEqual([b"Hello: 123"], list(resp.response))
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- @patch("opentelemetry.instrumentation.pyramid.callbacks._logger")
- def test_warnings(self, mock_logger):
- tween_list = "pyramid.tweens.excview_tween_factory"
- config = Configurator(settings={"pyramid.tweens": tween_list})
- PyramidInstrumentor().instrument_config(config)
- self._common_initialization(config)
-
- self.client.get("/hello/123")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 0)
- self.assertEqual(mock_logger.warning.called, True)
-
- mock_logger.warning.called = False
-
- tween_list = (
- "opentelemetry.instrumentation.pyramid.trace_tween_factory"
- )
- config = Configurator(settings={"pyramid.tweens": tween_list})
- self._common_initialization(config)
-
- self.client.get("/hello/123")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 0)
- self.assertEqual(mock_logger.warning.called, True)
-
- @patch(
- "opentelemetry.instrumentation.pyramid.callbacks._excluded_urls",
- ExcludeList(["http://localhost/excluded_arg/123", "excluded_noarg"]),
- )
- def test_exclude_lists(self):
- self.client.get("/excluded_arg/123")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 0)
-
- self.client.get("/excluded_arg/125")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- self.client.get("/excluded_noarg")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
-
- self.client.get("/excluded_noarg2")
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
diff --git a/instrumentation/opentelemetry-instrumentation-redis/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-redis/CHANGELOG.md
deleted file mode 100644
index 8f2d5f7e84f..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/CHANGELOG.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Update default SpanKind to `SpanKind.CLIENT` ([#965](https://github.com/open-telemetry/opentelemetry-python/pull/965))
-- Change package name to opentelemetry-instrumentation-redis
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-redis/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-redis/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-redis/README.rst b/instrumentation/opentelemetry-instrumentation-redis/README.rst
deleted file mode 100644
index 1a071ad0fee..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/README.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-OpenTelemetry Redis Instrumentation
-===================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-redis.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-redis/
-
-This library allows tracing requests made by the Redis library.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-redis
-
-
-References
-----------
-
-* `OpenTelemetry Redis Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-redis/setup.cfg b/instrumentation/opentelemetry-instrumentation-redis/setup.cfg
deleted file mode 100644
index 186e167dea2..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/setup.cfg
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-redis
-description = OpenTelemetry Redis instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-redis
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- redis >= 2.6
- wrapt >= 1.12.1
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
- opentelemetry-sdk == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- redis = opentelemetry.instrumentation.redis:RedisInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-redis/setup.py b/instrumentation/opentelemetry-instrumentation-redis/setup.py
deleted file mode 100644
index df80a8fd1aa..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "redis", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py
deleted file mode 100644
index e1c5db1e940..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-"""
-Instrument `redis`_ to report Redis queries.
-
-There are two options for instrumenting code. The first option is to use the
-``opentelemetry-instrumentation`` executable which will automatically
-instrument your Redis client. The second is to programmatically enable
-instrumentation via the following code:
-
-.. _redis: https://pypi.org/project/redis/
-
-Usage
------
-
-.. code:: python
-
- from opentelemetry import trace
- from opentelemetry.instrumentation.redis import RedisInstrumentor
- from opentelemetry.sdk.trace import TracerProvider
- import redis
-
- trace.set_tracer_provider(TracerProvider())
-
- # Instrument redis
- RedisInstrumentor().instrument(tracer_provider=trace.get_tracer_provider())
-
- # This will report a span with the default settings
- client = redis.StrictRedis(host="localhost", port=6379)
- client.get("my-key")
-
-API
----
-"""
-
-import redis
-from wrapt import ObjectProxy, wrap_function_wrapper
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.redis.util import (
- _extract_conn_attributes,
- _format_command_args,
-)
-from opentelemetry.instrumentation.redis.version import __version__
-from opentelemetry.instrumentation.utils import unwrap
-
-_DEFAULT_SERVICE = "redis"
-_RAWCMD = "db.statement"
-_CMD = "redis.command"
-
-
-def _set_connection_attributes(span, conn):
- if not span.is_recording():
- return
- for key, value in _extract_conn_attributes(
- conn.connection_pool.connection_kwargs
- ).items():
- span.set_attribute(key, value)
-
-
-def _traced_execute_command(func, instance, args, kwargs):
- tracer = getattr(redis, "_opentelemetry_tracer")
- query = _format_command_args(args)
- with tracer.start_as_current_span(
- _CMD, kind=trace.SpanKind.CLIENT
- ) as span:
- if span.is_recording():
- span.set_attribute("service", tracer.instrumentation_info.name)
- span.set_attribute(_RAWCMD, query)
- _set_connection_attributes(span, instance)
- span.set_attribute("redis.args_length", len(args))
- return func(*args, **kwargs)
-
-
-def _traced_execute_pipeline(func, instance, args, kwargs):
- tracer = getattr(redis, "_opentelemetry_tracer")
-
- cmds = [_format_command_args(c) for c, _ in instance.command_stack]
- resource = "\n".join(cmds)
-
- with tracer.start_as_current_span(
- _CMD, kind=trace.SpanKind.CLIENT
- ) as span:
- if span.is_recording():
- span.set_attribute("service", tracer.instrumentation_info.name)
- span.set_attribute(_RAWCMD, resource)
- _set_connection_attributes(span, instance)
- span.set_attribute(
- "redis.pipeline_length", len(instance.command_stack)
- )
- return func(*args, **kwargs)
-
-
-class RedisInstrumentor(BaseInstrumentor):
- """An instrumentor for Redis
- See `BaseInstrumentor`
- """
-
- def _instrument(self, **kwargs):
- tracer_provider = kwargs.get(
- "tracer_provider", trace.get_tracer_provider()
- )
- setattr(
- redis,
- "_opentelemetry_tracer",
- tracer_provider.get_tracer(_DEFAULT_SERVICE, __version__),
- )
-
- if redis.VERSION < (3, 0, 0):
- wrap_function_wrapper(
- "redis", "StrictRedis.execute_command", _traced_execute_command
- )
- wrap_function_wrapper(
- "redis.client",
- "BasePipeline.execute",
- _traced_execute_pipeline,
- )
- wrap_function_wrapper(
- "redis.client",
- "BasePipeline.immediate_execute_command",
- _traced_execute_command,
- )
- else:
- wrap_function_wrapper(
- "redis", "Redis.execute_command", _traced_execute_command
- )
- wrap_function_wrapper(
- "redis.client", "Pipeline.execute", _traced_execute_pipeline
- )
- wrap_function_wrapper(
- "redis.client",
- "Pipeline.immediate_execute_command",
- _traced_execute_command,
- )
-
- def _uninstrument(self, **kwargs):
- if redis.VERSION < (3, 0, 0):
- unwrap(redis.StrictRedis, "execute_command")
- unwrap(redis.StrictRedis, "pipeline")
- unwrap(redis.Redis, "pipeline")
- unwrap(
- redis.client.BasePipeline, # pylint:disable=no-member
- "execute",
- )
- unwrap(
- redis.client.BasePipeline, # pylint:disable=no-member
- "immediate_execute_command",
- )
- else:
- unwrap(redis.Redis, "execute_command")
- unwrap(redis.Redis, "pipeline")
- unwrap(redis.client.Pipeline, "execute")
- unwrap(redis.client.Pipeline, "immediate_execute_command")
diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/util.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/util.py
deleted file mode 100644
index 28951340893..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/util.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-"""
-Some utils used by the redis integration
-"""
-
-
-def _extract_conn_attributes(conn_kwargs):
- """ Transform redis conn info into dict """
- attributes = {
- "db.type": "redis",
- "db.instance": conn_kwargs.get("db", 0),
- }
- try:
- attributes["db.url"] = "redis://{}:{}".format(
- conn_kwargs["host"], conn_kwargs["port"]
- )
- except KeyError:
- pass # don't include url attribute
-
- return attributes
-
-
-def _format_command_args(args):
- """Format command arguments and trim them as needed"""
- value_max_len = 100
- value_too_long_mark = "..."
- cmd_max_len = 1000
- length = 0
- out = []
- for arg in args:
- cmd = str(arg)
-
- if len(cmd) > value_max_len:
- cmd = cmd[:value_max_len] + value_too_long_mark
-
- if length + len(cmd) > cmd_max_len:
- prefix = cmd[: cmd_max_len - length]
- out.append("%s%s" % (prefix, value_too_long_mark))
- break
-
- out.append(cmd)
- length += len(cmd)
-
- return " ".join(out)
diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/version.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-redis/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-redis/tests/__init__.py
deleted file mode 100644
index b0a6f428417..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/tests/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright The OpenTelemetry 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/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py b/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py
deleted file mode 100644
index 3e07ac725e2..00000000000
--- a/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest import mock
-
-import redis
-
-from opentelemetry.instrumentation.redis import RedisInstrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace import SpanKind
-
-
-class TestRedis(TestBase):
- def test_span_properties(self):
- redis_client = redis.Redis()
- RedisInstrumentor().instrument(tracer_provider=self.tracer_provider)
-
- with mock.patch.object(redis_client, "connection"):
- redis_client.get("key")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self.assertEqual(span.name, "redis.command")
- self.assertEqual(span.kind, SpanKind.CLIENT)
-
- def test_not_recording(self):
- redis_client = redis.Redis()
- RedisInstrumentor().instrument(tracer_provider=self.tracer_provider)
-
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- with mock.patch("opentelemetry.trace.get_tracer") as tracer:
- with mock.patch.object(redis_client, "connection"):
- tracer.return_value = mock_tracer
- redis_client.get("key")
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_instrument_uninstrument(self):
- redis_client = redis.Redis()
- RedisInstrumentor().instrument(tracer_provider=self.tracer_provider)
-
- with mock.patch.object(redis_client, "connection"):
- redis_client.get("key")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- self.memory_exporter.clear()
-
- # Test uninstrument
- RedisInstrumentor().uninstrument()
-
- with mock.patch.object(redis_client, "connection"):
- redis_client.get("key")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 0)
- self.memory_exporter.clear()
-
- # Test instrument again
- RedisInstrumentor().instrument()
-
- with mock.patch.object(redis_client, "connection"):
- redis_client.get("key")
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
diff --git a/instrumentation/opentelemetry-instrumentation-requests/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-requests/CHANGELOG.md
deleted file mode 100644
index 00d730f4f4d..00000000000
--- a/instrumentation/opentelemetry-instrumentation-requests/CHANGELOG.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.15b0
-
-Released 2020-11-02
-
-- Add support for tracking http metrics
- ([#1230](https://github.com/open-telemetry/opentelemetry-python/pull/1230))
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Add support for instrumenting prepared requests
- ([#1040](https://github.com/open-telemetry/opentelemetry-python/pull/1040))
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-- Add support for http metrics
- ([#1116](https://github.com/open-telemetry/opentelemetry-python/pull/1116))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-requests
- ([#961](https://github.com/open-telemetry/opentelemetry-python/pull/961))
-- Span name reported updated to follow semantic conventions to reduce
- cardinality ([#972](https://github.com/open-telemetry/opentelemetry-python/pull/972))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Rename package to opentelemetry-ext-requests
- ([#619](https://github.com/open-telemetry/opentelemetry-python/pull/619))
-- Implement instrumentor interface, enabling auto-instrumentation
- ([#597](https://github.com/open-telemetry/opentelemetry-python/pull/597))
-- Adding disable_session for more granular instrumentation control
- ([#573](https://github.com/open-telemetry/opentelemetry-python/pull/573))
-- Add a callback for custom attributes
- ([#656](https://github.com/open-telemetry/opentelemetry-python/pull/656))
-
-## 0.3a0
-
-Released 2019-10-29
-
-## 0.2a0
-
-Released 2019-10-29
-
-- Updates for core library changes
-
-## 0.1a0
-
-Released 2019-09-30
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-requests/LICENSE b/instrumentation/opentelemetry-instrumentation-requests/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-requests/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-requests/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-requests/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-requests/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-requests/README.rst b/instrumentation/opentelemetry-instrumentation-requests/README.rst
deleted file mode 100644
index d4944d35268..00000000000
--- a/instrumentation/opentelemetry-instrumentation-requests/README.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-OpenTelemetry Requests Instrumentation
-======================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-requests.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-requests/
-
-This library allows tracing HTTP requests made by the
-`requests `_ library.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-requests
-
-References
-----------
-
-* `OpenTelemetry requests Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-requests/setup.cfg b/instrumentation/opentelemetry-instrumentation-requests/setup.cfg
deleted file mode 100644
index 8aaec6e84ae..00000000000
--- a/instrumentation/opentelemetry-instrumentation-requests/setup.cfg
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-requests
-description = OpenTelemetry requests instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-requests
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- requests ~= 2.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
- httpretty ~= 1.0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- requests = opentelemetry.instrumentation.requests:RequestsInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-requests/setup.py b/instrumentation/opentelemetry-instrumentation-requests/setup.py
deleted file mode 100644
index 237fef583b9..00000000000
--- a/instrumentation/opentelemetry-instrumentation-requests/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "requests",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py
deleted file mode 100644
index b4738647dba..00000000000
--- a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py
+++ /dev/null
@@ -1,251 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-This library allows tracing HTTP requests made by the
-`requests `_ library.
-
-Usage
------
-
-.. code-block:: python
-
- import requests
- import opentelemetry.instrumentation.requests
-
- # You can optionally pass a custom TracerProvider to
- # RequestInstrumentor.instrument()
- opentelemetry.instrumentation.requests.RequestsInstrumentor().instrument()
- response = requests.get(url="https://www.example.org/")
-
-API
----
-"""
-
-import functools
-import types
-
-from requests import Timeout, URLRequired
-from requests.exceptions import InvalidSchema, InvalidURL, MissingSchema
-from requests.sessions import Session
-from requests.structures import CaseInsensitiveDict
-
-from opentelemetry import context, propagators
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.metric import (
- HTTPMetricRecorder,
- HTTPMetricType,
- MetricMixin,
-)
-from opentelemetry.instrumentation.requests.version import __version__
-from opentelemetry.instrumentation.utils import http_status_to_status_code
-from opentelemetry.trace import SpanKind, get_tracer
-from opentelemetry.trace.status import (
- EXCEPTION_STATUS_FIELD,
- Status,
- StatusCode,
-)
-
-# A key to a context variable to avoid creating duplicate spans when instrumenting
-# both, Session.request and Session.send, since Session.request calls into Session.send
-_SUPPRESS_REQUESTS_INSTRUMENTATION_KEY = "suppress_requests_instrumentation"
-
-
-# pylint: disable=unused-argument
-# pylint: disable=R0915
-def _instrument(tracer_provider=None, span_callback=None):
- """Enables tracing of all requests calls that go through
- :code:`requests.session.Session.request` (this includes
- :code:`requests.get`, etc.)."""
-
- # Since
- # https://github.com/psf/requests/commit/d72d1162142d1bf8b1b5711c664fbbd674f349d1
- # (v0.7.0, Oct 23, 2011), get, post, etc are implemented via request which
- # again, is implemented via Session.request (`Session` was named `session`
- # before v1.0.0, Dec 17, 2012, see
- # https://github.com/psf/requests/commit/4e5c4a6ab7bb0195dececdd19bb8505b872fe120)
-
- wrapped_request = Session.request
- wrapped_send = Session.send
-
- @functools.wraps(wrapped_request)
- def instrumented_request(self, method, url, *args, **kwargs):
- def get_or_create_headers():
- headers = kwargs.get("headers")
- if headers is None:
- headers = {}
- kwargs["headers"] = headers
-
- return headers
-
- def call_wrapped():
- return wrapped_request(self, method, url, *args, **kwargs)
-
- return _instrumented_requests_call(
- method, url, call_wrapped, get_or_create_headers
- )
-
- @functools.wraps(wrapped_send)
- def instrumented_send(self, request, **kwargs):
- def get_or_create_headers():
- request.headers = (
- request.headers
- if request.headers is not None
- else CaseInsensitiveDict()
- )
- return request.headers
-
- def call_wrapped():
- return wrapped_send(self, request, **kwargs)
-
- return _instrumented_requests_call(
- request.method, request.url, call_wrapped, get_or_create_headers
- )
-
- def _instrumented_requests_call(
- method: str, url: str, call_wrapped, get_or_create_headers
- ):
- if context.get_value("suppress_instrumentation") or context.get_value(
- _SUPPRESS_REQUESTS_INSTRUMENTATION_KEY
- ):
- return call_wrapped()
-
- # See
- # https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md#http-client
- method = method.upper()
- span_name = "HTTP {}".format(method)
-
- recorder = RequestsInstrumentor().metric_recorder
-
- labels = {}
- labels["http.method"] = method
- labels["http.url"] = url
-
- with get_tracer(
- __name__, __version__, tracer_provider
- ).start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
- exception = None
- with recorder.record_client_duration(labels):
- if span.is_recording():
- span.set_attribute("component", "http")
- span.set_attribute("http.method", method)
- span.set_attribute("http.url", url)
-
- headers = get_or_create_headers()
- propagators.inject(type(headers).__setitem__, headers)
-
- token = context.attach(
- context.set_value(
- _SUPPRESS_REQUESTS_INSTRUMENTATION_KEY, True
- )
- )
- try:
- result = call_wrapped() # *** PROCEED
- except Exception as exc: # pylint: disable=W0703
- exception = exc
- setattr(
- exception, EXCEPTION_STATUS_FIELD, StatusCode.ERROR,
- )
- result = getattr(exc, "response", None)
- finally:
- context.detach(token)
-
- if result is not None:
- if span.is_recording():
- span.set_attribute(
- "http.status_code", result.status_code
- )
- span.set_attribute("http.status_text", result.reason)
- span.set_status(
- Status(
- http_status_to_status_code(result.status_code)
- )
- )
- labels["http.status_code"] = str(result.status_code)
- if result.raw and result.raw.version:
- labels["http.flavor"] = (
- str(result.raw.version)[:1]
- + "."
- + str(result.raw.version)[:-1]
- )
- if span_callback is not None:
- span_callback(span, result)
-
- if exception is not None:
- raise exception.with_traceback(exception.__traceback__)
-
- return result
-
- instrumented_request.opentelemetry_instrumentation_requests_applied = True
- Session.request = instrumented_request
-
- instrumented_send.opentelemetry_instrumentation_requests_applied = True
- Session.send = instrumented_send
-
-
-def _uninstrument():
- """Disables instrumentation of :code:`requests` through this module.
-
- Note that this only works if no other module also patches requests."""
- _uninstrument_from(Session)
-
-
-def _uninstrument_from(instr_root, restore_as_bound_func=False):
- for instr_func_name in ("request", "send"):
- instr_func = getattr(instr_root, instr_func_name)
- if not getattr(
- instr_func,
- "opentelemetry_instrumentation_requests_applied",
- False,
- ):
- continue
-
- original = instr_func.__wrapped__ # pylint:disable=no-member
- if restore_as_bound_func:
- original = types.MethodType(original, instr_root)
- setattr(instr_root, instr_func_name, original)
-
-
-class RequestsInstrumentor(BaseInstrumentor, MetricMixin):
- """An instrumentor for requests
- See `BaseInstrumentor`
- """
-
- def _instrument(self, **kwargs):
- """Instruments requests module
-
- Args:
- **kwargs: Optional arguments
- ``tracer_provider``: a TracerProvider, defaults to global
- ``span_callback``: An optional callback invoked before returning the http response. Invoked with Span and requests.Response
- """
- _instrument(
- tracer_provider=kwargs.get("tracer_provider"),
- span_callback=kwargs.get("span_callback"),
- )
- self.init_metrics(
- __name__, __version__,
- )
- # pylint: disable=W0201
- self.metric_recorder = HTTPMetricRecorder(
- self.meter, HTTPMetricType.CLIENT
- )
-
- def _uninstrument(self, **kwargs):
- _uninstrument()
-
- @staticmethod
- def uninstrument_session(session):
- """Disables instrumentation on the session object."""
- _uninstrument_from(session, restore_as_bound_func=True)
diff --git a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/version.py b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-requests/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-requests/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py
deleted file mode 100644
index f5209108e33..00000000000
--- a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py
+++ /dev/null
@@ -1,380 +0,0 @@
-# Copyright The OpenTelemetry 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 abc
-from unittest import mock
-
-import httpretty
-import requests
-
-import opentelemetry.instrumentation.requests
-from opentelemetry import context, propagators, trace
-from opentelemetry.instrumentation.requests import RequestsInstrumentor
-from opentelemetry.sdk import resources
-from opentelemetry.sdk.util import get_dict_as_key
-from opentelemetry.test.mock_textmap import MockTextMapPropagator
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace.status import StatusCode
-
-
-class RequestsIntegrationTestBase(abc.ABC):
- # pylint: disable=no-member
-
- URL = "http://httpbin.org/status/200"
-
- # pylint: disable=invalid-name
- def setUp(self):
- super().setUp()
- RequestsInstrumentor().instrument()
- httpretty.enable()
- httpretty.register_uri(httpretty.GET, self.URL, body="Hello!")
-
- # pylint: disable=invalid-name
- def tearDown(self):
- super().tearDown()
- RequestsInstrumentor().uninstrument()
- httpretty.disable()
-
- def assert_span(self, exporter=None, num_spans=1):
- if exporter is None:
- exporter = self.memory_exporter
- span_list = exporter.get_finished_spans()
- self.assertEqual(num_spans, len(span_list))
- if num_spans == 0:
- return None
- if num_spans == 1:
- return span_list[0]
- return span_list
-
- @staticmethod
- @abc.abstractmethod
- def perform_request(url: str, session: requests.Session = None):
- pass
-
- def test_basic(self):
- result = self.perform_request(self.URL)
- self.assertEqual(result.text, "Hello!")
- span = self.assert_span()
-
- self.assertIs(span.kind, trace.SpanKind.CLIENT)
- self.assertEqual(span.name, "HTTP GET")
-
- self.assertEqual(
- span.attributes,
- {
- "component": "http",
- "http.method": "GET",
- "http.url": self.URL,
- "http.status_code": 200,
- "http.status_text": "OK",
- },
- )
-
- self.assertIs(span.status.status_code, trace.status.StatusCode.UNSET)
-
- self.check_span_instrumentation_info(
- span, opentelemetry.instrumentation.requests
- )
-
- self.assertIsNotNone(RequestsInstrumentor().meter)
- self.assertEqual(len(RequestsInstrumentor().meter.metrics), 1)
- recorder = RequestsInstrumentor().meter.metrics.pop()
- match_key = get_dict_as_key(
- {
- "http.flavor": "1.1",
- "http.method": "GET",
- "http.status_code": "200",
- "http.url": "http://httpbin.org/status/200",
- }
- )
- for key in recorder.bound_instruments.keys():
- self.assertEqual(key, match_key)
- # pylint: disable=protected-access
- bound = recorder.bound_instruments.get(key)
- for view_data in bound.view_datas:
- self.assertEqual(view_data.labels, key)
- self.assertEqual(view_data.aggregator.current.count, 1)
- self.assertGreaterEqual(view_data.aggregator.current.sum, 0)
-
- def test_not_foundbasic(self):
- url_404 = "http://httpbin.org/status/404"
- httpretty.register_uri(
- httpretty.GET, url_404, status=404,
- )
- result = self.perform_request(url_404)
- self.assertEqual(result.status_code, 404)
-
- span = self.assert_span()
-
- self.assertEqual(span.attributes.get("http.status_code"), 404)
- self.assertEqual(span.attributes.get("http.status_text"), "Not Found")
-
- self.assertIs(
- span.status.status_code, trace.status.StatusCode.ERROR,
- )
-
- def test_uninstrument(self):
- RequestsInstrumentor().uninstrument()
- result = self.perform_request(self.URL)
- self.assertEqual(result.text, "Hello!")
- self.assert_span(num_spans=0)
- # instrument again to avoid annoying warning message
- RequestsInstrumentor().instrument()
-
- def test_uninstrument_session(self):
- session1 = requests.Session()
- RequestsInstrumentor().uninstrument_session(session1)
-
- result = self.perform_request(self.URL, session1)
- self.assertEqual(result.text, "Hello!")
- self.assert_span(num_spans=0)
-
- # Test that other sessions as well as global requests is still
- # instrumented
- session2 = requests.Session()
- result = self.perform_request(self.URL, session2)
- self.assertEqual(result.text, "Hello!")
- self.assert_span()
-
- self.memory_exporter.clear()
-
- result = self.perform_request(self.URL)
- self.assertEqual(result.text, "Hello!")
- self.assert_span()
-
- def test_suppress_instrumentation(self):
- token = context.attach(
- context.set_value("suppress_instrumentation", True)
- )
- try:
- result = self.perform_request(self.URL)
- self.assertEqual(result.text, "Hello!")
- finally:
- context.detach(token)
-
- self.assert_span(num_spans=0)
-
- def test_not_recording(self):
- with mock.patch("opentelemetry.trace.INVALID_SPAN") as mock_span:
- RequestsInstrumentor().uninstrument()
- # original_tracer_provider returns a default tracer provider, which
- # in turn will return an INVALID_SPAN, which is always not recording
- RequestsInstrumentor().instrument(
- tracer_provider=self.original_tracer_provider
- )
- mock_span.is_recording.return_value = False
- result = self.perform_request(self.URL)
- self.assertEqual(result.text, "Hello!")
- self.assert_span(None, 0)
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_distributed_context(self):
- previous_propagator = propagators.get_global_textmap()
- try:
- propagators.set_global_textmap(MockTextMapPropagator())
- result = self.perform_request(self.URL)
- self.assertEqual(result.text, "Hello!")
-
- span = self.assert_span()
-
- headers = dict(httpretty.last_request().headers)
- self.assertIn(MockTextMapPropagator.TRACE_ID_KEY, headers)
- self.assertEqual(
- str(span.get_span_context().trace_id),
- headers[MockTextMapPropagator.TRACE_ID_KEY],
- )
- self.assertIn(MockTextMapPropagator.SPAN_ID_KEY, headers)
- self.assertEqual(
- str(span.get_span_context().span_id),
- headers[MockTextMapPropagator.SPAN_ID_KEY],
- )
-
- finally:
- propagators.set_global_textmap(previous_propagator)
-
- def test_span_callback(self):
- RequestsInstrumentor().uninstrument()
-
- def span_callback(span, result: requests.Response):
- span.set_attribute(
- "http.response.body", result.content.decode("utf-8")
- )
-
- RequestsInstrumentor().instrument(
- tracer_provider=self.tracer_provider, span_callback=span_callback,
- )
-
- result = self.perform_request(self.URL)
- self.assertEqual(result.text, "Hello!")
-
- span = self.assert_span()
- self.assertEqual(
- span.attributes,
- {
- "component": "http",
- "http.method": "GET",
- "http.url": self.URL,
- "http.status_code": 200,
- "http.status_text": "OK",
- "http.response.body": "Hello!",
- },
- )
-
- def test_custom_tracer_provider(self):
- resource = resources.Resource.create({})
- result = self.create_tracer_provider(resource=resource)
- tracer_provider, exporter = result
- RequestsInstrumentor().uninstrument()
- RequestsInstrumentor().instrument(tracer_provider=tracer_provider)
-
- result = self.perform_request(self.URL)
- self.assertEqual(result.text, "Hello!")
-
- span = self.assert_span(exporter=exporter)
- self.assertIs(span.resource, resource)
-
- @mock.patch(
- "requests.adapters.HTTPAdapter.send",
- side_effect=requests.RequestException,
- )
- def test_requests_exception_without_response(self, *_, **__):
- with self.assertRaises(requests.RequestException):
- self.perform_request(self.URL)
-
- span = self.assert_span()
- self.assertEqual(
- span.attributes,
- {"component": "http", "http.method": "GET", "http.url": self.URL},
- )
- self.assertEqual(span.status.status_code, StatusCode.ERROR)
-
- self.assertIsNotNone(RequestsInstrumentor().meter)
- self.assertEqual(len(RequestsInstrumentor().meter.metrics), 1)
- recorder = RequestsInstrumentor().meter.metrics.pop()
- match_key = get_dict_as_key(
- {
- "http.method": "GET",
- "http.url": "http://httpbin.org/status/200",
- }
- )
- for key in recorder.bound_instruments.keys():
- self.assertEqual(key, match_key)
- # pylint: disable=protected-access
- bound = recorder.bound_instruments.get(key)
- for view_data in bound.view_datas:
- self.assertEqual(view_data.labels, key)
- self.assertEqual(view_data.aggregator.current.count, 1)
-
- mocked_response = requests.Response()
- mocked_response.status_code = 500
- mocked_response.reason = "Internal Server Error"
-
- @mock.patch(
- "requests.adapters.HTTPAdapter.send",
- side_effect=requests.RequestException(response=mocked_response),
- )
- def test_requests_exception_with_response(self, *_, **__):
- with self.assertRaises(requests.RequestException):
- self.perform_request(self.URL)
-
- span = self.assert_span()
- self.assertEqual(
- span.attributes,
- {
- "component": "http",
- "http.method": "GET",
- "http.url": self.URL,
- "http.status_code": 500,
- "http.status_text": "Internal Server Error",
- },
- )
- self.assertEqual(span.status.status_code, StatusCode.ERROR)
- self.assertIsNotNone(RequestsInstrumentor().meter)
- self.assertEqual(len(RequestsInstrumentor().meter.metrics), 1)
- recorder = RequestsInstrumentor().meter.metrics.pop()
- match_key = get_dict_as_key(
- {
- "http.method": "GET",
- "http.status_code": "500",
- "http.url": "http://httpbin.org/status/200",
- }
- )
- for key in recorder.bound_instruments.keys():
- self.assertEqual(key, match_key)
- # pylint: disable=protected-access
- bound = recorder.bound_instruments.get(key)
- for view_data in bound.view_datas:
- self.assertEqual(view_data.labels, key)
- self.assertEqual(view_data.aggregator.current.count, 1)
-
- @mock.patch("requests.adapters.HTTPAdapter.send", side_effect=Exception)
- def test_requests_basic_exception(self, *_, **__):
- with self.assertRaises(Exception):
- self.perform_request(self.URL)
-
- span = self.assert_span()
- self.assertEqual(span.status.status_code, StatusCode.ERROR)
-
- @mock.patch(
- "requests.adapters.HTTPAdapter.send", side_effect=requests.Timeout
- )
- def test_requests_timeout_exception(self, *_, **__):
- with self.assertRaises(Exception):
- self.perform_request(self.URL)
-
- span = self.assert_span()
- self.assertEqual(span.status.status_code, StatusCode.ERROR)
-
-
-class TestRequestsIntegration(RequestsIntegrationTestBase, TestBase):
- @staticmethod
- def perform_request(url: str, session: requests.Session = None):
- if session is None:
- return requests.get(url)
- return session.get(url)
-
- def test_invalid_url(self):
- url = "http://[::1/nope"
-
- with self.assertRaises(ValueError):
- requests.post(url)
-
- span = self.assert_span()
-
- self.assertEqual(span.name, "HTTP POST")
- self.assertEqual(
- span.attributes,
- {"component": "http", "http.method": "POST", "http.url": url},
- )
- self.assertEqual(span.status.status_code, StatusCode.ERROR)
-
- def test_if_headers_equals_none(self):
- result = requests.get(self.URL, headers=None)
- self.assertEqual(result.text, "Hello!")
- self.assert_span()
-
-
-class TestRequestsIntegrationPreparedRequest(
- RequestsIntegrationTestBase, TestBase
-):
- @staticmethod
- def perform_request(url: str, session: requests.Session = None):
- if session is None:
- session = requests.Session()
- request = requests.Request("GET", url)
- prepared_request = session.prepare_request(request)
- return session.send(prepared_request)
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-sqlalchemy/CHANGELOG.md
deleted file mode 100644
index 73fa087a119..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/CHANGELOG.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-sqlalchemy
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## 0.7b1
-
-Released 2020-05-12
-
-- Initial release
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/LICENSE b/instrumentation/opentelemetry-instrumentation-sqlalchemy/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-sqlalchemy/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-sqlalchemy/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/README.rst b/instrumentation/opentelemetry-instrumentation-sqlalchemy/README.rst
deleted file mode 100644
index f29cbe9ffff..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/README.rst
+++ /dev/null
@@ -1,24 +0,0 @@
-OpenTelemetry SQLAlchemy Instrumentation
-========================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-sqlalchemy.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-sqlalchemy/
-
-This library allows tracing requests made by the SQLAlchemy library.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-sqlalchemy
-
-
-References
-----------
-
-* `SQLAlchemy Project `_
-* `OpenTelemetry SQLAlchemy Tracing `_
-* `OpenTelemetry Project `_
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.cfg b/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.cfg
deleted file mode 100644
index c6b44013cea..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.cfg
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-sqlalchemy
-description = OpenTelemetry SQLAlchemy instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-sqlalchemy
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- wrapt >= 1.11.2
- sqlalchemy
-
-[options.extras_require]
-test =
- opentelemetry-sdk == 0.16.dev0
- pytest
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- sqlalchemy = opentelemetry.instrumentation.sqlalchemy:SQLAlchemyInstrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.py
deleted file mode 100644
index 26d3ef4fc92..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "sqlalchemy",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py
deleted file mode 100644
index aad6dbfc07c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/__init__.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-Instrument `sqlalchemy`_ to report SQL queries.
-
-There are two options for instrumenting code. The first option is to use
-the ``opentelemetry-instrument`` executable which will automatically
-instrument your SQLAlchemy engine. The second is to programmatically enable
-instrumentation via the following code:
-
-.. _sqlalchemy: https://pypi.org/project/sqlalchemy/
-
-Usage
------
-.. code:: python
-
- from sqlalchemy import create_engine
-
- from opentelemetry import trace
- from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
- from opentelemetry.sdk.trace import TracerProvider
- import sqlalchemy
-
- trace.set_tracer_provider(TracerProvider())
- engine = create_engine("sqlite:///:memory:")
- SQLAlchemyInstrumentor().instrument(
- engine=engine,
- service="service-A",
- )
-
-API
----
-"""
-import sqlalchemy
-import wrapt
-from wrapt import wrap_function_wrapper as _w
-
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.sqlalchemy.engine import (
- EngineTracer,
- _get_tracer,
- _wrap_create_engine,
-)
-from opentelemetry.instrumentation.utils import unwrap
-
-
-class SQLAlchemyInstrumentor(BaseInstrumentor):
- """An instrumentor for SQLAlchemy
- See `BaseInstrumentor`
- """
-
- def _instrument(self, **kwargs):
- """Instruments SQLAlchemy engine creation methods and the engine
- if passed as an argument.
-
- Args:
- **kwargs: Optional arguments
- ``engine``: a SQLAlchemy engine instance
- ``tracer_provider``: a TracerProvider, defaults to global
- ``service``: the name of the service to trace.
-
- Returns:
- An instrumented engine if passed in as an argument, None otherwise.
- """
- _w("sqlalchemy", "create_engine", _wrap_create_engine)
- _w("sqlalchemy.engine", "create_engine", _wrap_create_engine)
- if kwargs.get("engine") is not None:
- return EngineTracer(
- _get_tracer(
- kwargs.get("engine"), kwargs.get("tracer_provider")
- ),
- kwargs.get("service"),
- kwargs.get("engine"),
- )
- return None
-
- def _uninstrument(self, **kwargs):
- unwrap(sqlalchemy, "create_engine")
- unwrap(sqlalchemy.engine, "create_engine")
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py
deleted file mode 100644
index 7c97c685da5..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# Copyright The OpenTelemetry 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 sqlalchemy.event import listen
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.sqlalchemy.version import __version__
-from opentelemetry.trace.status import Status, StatusCode
-
-# Network attribute semantic convention here:
-# https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/span-general.md#general-network-connection-attributes
-_HOST = "net.peer.name"
-_PORT = "net.peer.port"
-# Database semantic conventions here:
-# https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/database.md
-_ROWS = "sql.rows" # number of rows returned by a query
-_STMT = "db.statement"
-_DB = "db.type"
-_URL = "db.url"
-
-
-def _normalize_vendor(vendor):
- """Return a canonical name for a type of database."""
- if not vendor:
- return "db" # should this ever happen?
-
- if "sqlite" in vendor:
- return "sqlite"
-
- if "postgres" in vendor or vendor == "psycopg2":
- return "postgres"
-
- return vendor
-
-
-def _get_tracer(engine, tracer_provider=None):
- if tracer_provider is None:
- tracer_provider = trace.get_tracer_provider()
- return tracer_provider.get_tracer(
- _normalize_vendor(engine.name), __version__
- )
-
-
-# pylint: disable=unused-argument
-def _wrap_create_engine(func, module, args, kwargs):
- """Trace the SQLAlchemy engine, creating an `EngineTracer`
- object that will listen to SQLAlchemy events.
- """
- engine = func(*args, **kwargs)
- EngineTracer(_get_tracer(engine), None, engine)
- return engine
-
-
-class EngineTracer:
- def __init__(self, tracer, service, engine):
- self.tracer = tracer
- self.engine = engine
- self.vendor = _normalize_vendor(engine.name)
- self.service = service or self.vendor
- self.name = "%s.query" % self.vendor
- self.current_span = None
-
- listen(engine, "before_cursor_execute", self._before_cur_exec)
- listen(engine, "after_cursor_execute", self._after_cur_exec)
- listen(engine, "handle_error", self._handle_error)
-
- # pylint: disable=unused-argument
- def _before_cur_exec(self, conn, cursor, statement, *args):
- self.current_span = self.tracer.start_span(self.name)
- with self.tracer.use_span(self.current_span, end_on_exit=False):
- if self.current_span.is_recording():
- self.current_span.set_attribute("service", self.vendor)
- self.current_span.set_attribute(_STMT, statement)
-
- if not _set_attributes_from_url(
- self.current_span, conn.engine.url
- ):
- _set_attributes_from_cursor(
- self.current_span, self.vendor, cursor
- )
-
- # pylint: disable=unused-argument
- def _after_cur_exec(self, conn, cursor, statement, *args):
- if self.current_span is None:
- return
-
- try:
- if (
- cursor
- and cursor.rowcount >= 0
- and self.current_span.is_recording()
- ):
- self.current_span.set_attribute(_ROWS, cursor.rowcount)
- finally:
- self.current_span.end()
-
- def _handle_error(self, context):
- if self.current_span is None:
- return
-
- try:
- if self.current_span.is_recording():
- self.current_span.set_status(
- Status(StatusCode.ERROR, str(context.original_exception),)
- )
- finally:
- self.current_span.end()
-
-
-def _set_attributes_from_url(span: trace.Span, url):
- """Set connection tags from the url. return true if successful."""
- if span.is_recording():
- if url.host:
- span.set_attribute(_HOST, url.host)
- if url.port:
- span.set_attribute(_PORT, url.port)
- if url.database:
- span.set_attribute(_DB, url.database)
-
- return bool(url.host)
-
-
-def _set_attributes_from_cursor(span: trace.Span, vendor, cursor):
- """Attempt to set db connection attributes by introspecting the cursor."""
- if not span.is_recording():
- return
- if vendor == "postgres":
- # pylint: disable=import-outside-toplevel
- from psycopg2.extensions import parse_dsn
-
- if hasattr(cursor, "connection") and hasattr(cursor.connection, "dsn"):
- dsn = getattr(cursor.connection, "dsn", None)
- if dsn:
- data = parse_dsn(dsn)
- span.set_attribute(_DB, data.get("dbname"))
- span.set_attribute(_HOST, data.get("host"))
- span.set_attribute(_PORT, int(data.get("port")))
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/version.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/__init__.py
deleted file mode 100644
index b0a6f428417..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright The OpenTelemetry 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/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py
deleted file mode 100644
index 3b2e3548a5c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest import mock
-
-from sqlalchemy import create_engine
-
-from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
-from opentelemetry.test.test_base import TestBase
-
-
-class TestSqlalchemyInstrumentation(TestBase):
- def tearDown(self):
- super().tearDown()
- SQLAlchemyInstrumentor().uninstrument()
-
- def test_trace_integration(self):
- engine = create_engine("sqlite:///:memory:")
- SQLAlchemyInstrumentor().instrument(
- engine=engine,
- tracer_provider=self.tracer_provider,
- service="my-database",
- )
- cnx = engine.connect()
- cnx.execute("SELECT 1 + 1;").fetchall()
- spans = self.memory_exporter.get_finished_spans()
-
- self.assertEqual(len(spans), 1)
- self.assertEqual(spans[0].name, "sqlite.query")
-
- def test_not_recording(self):
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- with mock.patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- engine = create_engine("sqlite:///:memory:")
- SQLAlchemyInstrumentor().instrument(
- engine=engine,
- tracer_provider=self.tracer_provider,
- service="my-database",
- )
- cnx = engine.connect()
- cnx.execute("SELECT 1 + 1;").fetchall()
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_create_engine_wrapper(self):
- SQLAlchemyInstrumentor().instrument()
- from sqlalchemy import create_engine # pylint: disable-all
-
- engine = create_engine("sqlite:///:memory:")
- cnx = engine.connect()
- cnx.execute("SELECT 1 + 1;").fetchall()
- spans = self.memory_exporter.get_finished_spans()
-
- self.assertEqual(len(spans), 1)
- self.assertEqual(spans[0].name, "sqlite.query")
diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-sqlite3/CHANGELOG.md
deleted file mode 100644
index 39545604081..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlite3/CHANGELOG.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-sqlite3
- ([#966](https://github.com/open-telemetry/opentelemetry-python/pull/966))
-
-## 0.8b0
-
-Released 2020-05-27
-
-- Initial release
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/LICENSE b/instrumentation/opentelemetry-instrumentation-sqlite3/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlite3/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-sqlite3/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-sqlite3/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlite3/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/README.rst b/instrumentation/opentelemetry-instrumentation-sqlite3/README.rst
deleted file mode 100644
index 0d2aa2dd992..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlite3/README.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-OpenTelemetry SQLite3 Instrumentation
-=====================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-sqlite3.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-sqlite3/
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-sqlite3
-
-
-References
-----------
-* `OpenTelemetry SQLite3 Instrumentation `_
-* `OpenTelemetry Project `_
-
diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/setup.cfg b/instrumentation/opentelemetry-instrumentation-sqlite3/setup.cfg
deleted file mode 100644
index d8145be3911..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlite3/setup.cfg
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-sqlite3
-description = OpenTelemetry SQLite3 instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-sqlite3
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation-dbapi == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
- wrapt >= 1.0.0, < 2.0.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
-
-[options.entry_points]
-opentelemetry_instrumentor =
- sqlite3 = opentelemetry.instrumentation.sqlite3:SQLite3Instrumentor
diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/setup.py b/instrumentation/opentelemetry-instrumentation-sqlite3/setup.py
deleted file mode 100644
index 67ce350fab5..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlite3/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "sqlite3",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py
deleted file mode 100644
index 568e83f0d6a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-SQLite instrumentation supporting `sqlite3`_, it can be enabled by
-using ``SQLite3Instrumentor``.
-
-.. _sqlite3: https://docs.python.org/3/library/sqlite3.html
-
-Usage
------
-
-.. code:: python
-
- import sqlite3
- from opentelemetry import trace
- from opentelemetry.trace import TracerProvider
- from opentelemetry.instrumentation.sqlite3 import SQLite3Instrumentor
-
- trace.set_tracer_provider(TracerProvider())
-
- SQLite3Instrumentor().instrument()
-
- cnx = sqlite3.connect('example.db')
- cursor = cnx.cursor()
- cursor.execute("INSERT INTO test (testField) VALUES (123)")
- cursor.close()
- cnx.close()
-
-API
----
-"""
-
-import sqlite3
-
-from opentelemetry.instrumentation import dbapi
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.sqlite3.version import __version__
-from opentelemetry.trace import get_tracer
-
-
-class SQLite3Instrumentor(BaseInstrumentor):
- # No useful attributes of sqlite3 connection object
- _CONNECTION_ATTRIBUTES = {}
-
- _DATABASE_COMPONENT = "sqlite3"
- _DATABASE_TYPE = "sql"
-
- def _instrument(self, **kwargs):
- """Integrate with SQLite3 Python library.
- https://docs.python.org/3/library/sqlite3.html
- """
- tracer_provider = kwargs.get("tracer_provider")
-
- dbapi.wrap_connect(
- __name__,
- sqlite3,
- "connect",
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- version=__version__,
- tracer_provider=tracer_provider,
- )
-
- def _uninstrument(self, **kwargs):
- """"Disable SQLite3 instrumentation"""
- dbapi.unwrap_connect(sqlite3, "connect")
-
- # pylint:disable=no-self-use
- def instrument_connection(self, connection):
- """Enable instrumentation in a SQLite connection.
-
- Args:
- connection: The connection to instrument.
-
- Returns:
- An instrumented connection.
- """
- tracer = get_tracer(__name__, __version__)
-
- return dbapi.instrument_connection(
- tracer,
- connection,
- self._DATABASE_COMPONENT,
- self._DATABASE_TYPE,
- self._CONNECTION_ATTRIBUTES,
- )
-
- def uninstrument_connection(self, connection):
- """Disable instrumentation in a SQLite connection.
-
- Args:
- connection: The connection to uninstrument.
-
- Returns:
- An uninstrumented connection.
- """
- return dbapi.uninstrument_connection(connection)
diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/version.py b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlite3/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/tests/test_sqlite3.py b/instrumentation/opentelemetry-instrumentation-sqlite3/tests/test_sqlite3.py
deleted file mode 100644
index 0e385cf3e76..00000000000
--- a/instrumentation/opentelemetry-instrumentation-sqlite3/tests/test_sqlite3.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright 2020, OpenTelemetry 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 sqlite3
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.sqlite3 import SQLite3Instrumentor
-from opentelemetry.test.test_base import TestBase
-
-
-class TestSQLite3(TestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls._connection = None
- cls._cursor = None
- cls._tracer = cls.tracer_provider.get_tracer(__name__)
- SQLite3Instrumentor().instrument(tracer_provider=cls.tracer_provider)
- cls._connection = sqlite3.connect(":memory:")
- cls._cursor = cls._connection.cursor()
-
- @classmethod
- def tearDownClass(cls):
- if cls._cursor:
- cls._cursor.close()
- if cls._connection:
- cls._connection.close()
-
- def validate_spans(self):
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
- for span in spans:
- if span.name == "rootSpan":
- root_span = span
- else:
- child_span = span
- self.assertIsInstance(span.start_time, int)
- self.assertIsInstance(span.end_time, int)
- self.assertIsNotNone(root_span)
- self.assertIsNotNone(child_span)
- self.assertEqual(root_span.name, "rootSpan")
- self.assertEqual(child_span.name, "sqlite3")
- self.assertIsNotNone(child_span.parent)
- self.assertIs(child_span.parent, root_span.get_span_context())
- self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT)
-
- def test_execute(self):
- """Should create a child span for execute method
- """
- with self._tracer.start_as_current_span("rootSpan"):
- self._cursor.execute(
- "CREATE TABLE IF NOT EXISTS test (id integer)"
- )
- self.validate_spans()
-
- def test_executemany(self):
- """Should create a child span for executemany
- """
- with self._tracer.start_as_current_span("rootSpan"):
- data = [("1",), ("2",), ("3",)]
- stmt = "INSERT INTO test (id) VALUES (?)"
- self._cursor.executemany(stmt, data)
- self.validate_spans()
-
- def test_callproc(self):
- """Should create a child span for callproc
- """
- with self._tracer.start_as_current_span("rootSpan"), self.assertRaises(
- Exception
- ):
- self._cursor.callproc("test", ())
- self.validate_spans()
diff --git a/instrumentation/opentelemetry-instrumentation-starlette/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-starlette/CHANGELOG.md
deleted file mode 100644
index 1991025f6cb..00000000000
--- a/instrumentation/opentelemetry-instrumentation-starlette/CHANGELOG.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.10b0
-
-Released 2020-06-23
-
-- Initial release ([#777](https://github.com/open-telemetry/opentelemetry-python/pull/777))
\ No newline at end of file
diff --git a/instrumentation/opentelemetry-instrumentation-starlette/README.rst b/instrumentation/opentelemetry-instrumentation-starlette/README.rst
deleted file mode 100644
index 1d05c0b717f..00000000000
--- a/instrumentation/opentelemetry-instrumentation-starlette/README.rst
+++ /dev/null
@@ -1,45 +0,0 @@
-OpenTelemetry Starlette Instrumentation
-=======================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-starlette.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-starlette/
-
-
-This library provides automatic and manual instrumentation of Starlette web frameworks,
-instrumenting http requests served by applications utilizing the framework.
-
-auto-instrumentation using the opentelemetry-instrumentation package is also supported.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-starlette
-
-
-Usage
------
-
-.. code-block:: python
-
- from opentelemetry.instrumentation.starlette import StarletteInstrumentor
- from starlette import applications
- from starlette.responses import PlainTextResponse
- from starlette.routing import Route
-
- def home(request):
- return PlainTextResponse("hi")
-
- app = applications.Starlette(
- routes=[Route("/foobar", home)]
- )
- StarletteInstrumentor.instrument_app(app)
-
-
-References
-----------
-
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg b/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg
deleted file mode 100644
index 04b1f3cbec7..00000000000
--- a/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-starlette
-description = OpenTelemetry Starlette Instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-starlette
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.6
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation-asgi == 0.16.dev0
-
-[options.entry_points]
-opentelemetry_instrumentor =
- starlette = opentelemetry.instrumentation.starlette:StarletteInstrumentor
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
- starlette ~= 0.13.0
- requests ~= 2.23.0 # needed for testclient
-
-[options.packages.find]
-where = src
diff --git a/instrumentation/opentelemetry-instrumentation-starlette/setup.py b/instrumentation/opentelemetry-instrumentation-starlette/setup.py
deleted file mode 100644
index 0232a6f448c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-starlette/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "starlette",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py
deleted file mode 100644
index f469447f3ac..00000000000
--- a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright The OpenTelemetry 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 typing import Optional
-
-from starlette import applications
-from starlette.routing import Match
-
-from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.starlette.version import __version__ # noqa
-
-
-class StarletteInstrumentor(BaseInstrumentor):
- """An instrumentor for starlette
-
- See `BaseInstrumentor`
- """
-
- _original_starlette = None
-
- @staticmethod
- def instrument_app(app: applications.Starlette):
- """Instrument an uninstrumented Starlette application.
- """
- if not getattr(app, "is_instrumented_by_opentelemetry", False):
- app.add_middleware(
- OpenTelemetryMiddleware,
- span_details_callback=_get_route_details,
- )
- app.is_instrumented_by_opentelemetry = True
-
- def _instrument(self, **kwargs):
- self._original_starlette = applications.Starlette
- applications.Starlette = _InstrumentedStarlette
-
- def _uninstrument(self, **kwargs):
- applications.Starlette = self._original_starlette
-
-
-class _InstrumentedStarlette(applications.Starlette):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.add_middleware(
- OpenTelemetryMiddleware, span_details_callback=_get_route_details
- )
-
-
-def _get_route_details(scope):
- """Callback to retrieve the starlette route being served.
-
- TODO: there is currently no way to retrieve http.route from
- a starlette application from scope.
-
- See: https://github.com/encode/starlette/pull/804
- """
- app = scope["app"]
- route = None
- for starlette_route in app.routes:
- match, _ = starlette_route.matches(scope)
- if match == Match.FULL:
- route = starlette_route.path
- break
- if match == Match.PARTIAL:
- route = starlette_route.path
- # method only exists for http, if websocket
- # leave it blank.
- span_name = route or scope.get("method", "")
- attributes = {}
- if route:
- attributes["http.route"] = route
- return span_name, attributes
diff --git a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/version.py b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-starlette/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-starlette/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py
deleted file mode 100644
index a49db07c9a7..00000000000
--- a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest
-
-from starlette import applications
-from starlette.responses import PlainTextResponse
-from starlette.routing import Route
-from starlette.testclient import TestClient
-
-import opentelemetry.instrumentation.starlette as otel_starlette
-from opentelemetry.test.test_base import TestBase
-
-
-class TestStarletteManualInstrumentation(TestBase):
- def _create_app(self):
- app = self._create_starlette_app()
- self._instrumentor.instrument_app(app)
- return app
-
- def setUp(self):
- super().setUp()
- self._instrumentor = otel_starlette.StarletteInstrumentor()
- self._app = self._create_app()
- self._client = TestClient(self._app)
-
- def test_basic_starlette_call(self):
- self._client.get("/foobar")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 3)
- for span in spans:
- self.assertIn("/foobar", span.name)
-
- def test_starlette_route_attribute_added(self):
- """Ensure that starlette routes are used as the span name."""
- self._client.get("/user/123")
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 3)
- for span in spans:
- self.assertIn("/user/{username}", span.name)
- self.assertEqual(
- spans[-1].attributes["http.route"], "/user/{username}"
- )
- # ensure that at least one attribute that is populated by
- # the asgi instrumentation is successfully feeding though.
- self.assertEqual(spans[-1].attributes["http.flavor"], "1.1")
-
- @staticmethod
- def _create_starlette_app():
- def home(_):
- return PlainTextResponse("hi")
-
- app = applications.Starlette(
- routes=[Route("/foobar", home), Route("/user/{username}", home)]
- )
- return app
-
-
-class TestAutoInstrumentation(TestStarletteManualInstrumentation):
- """Test the auto-instrumented variant
-
- Extending the manual instrumentation as most test cases apply
- to both.
- """
-
- def _create_app(self):
- # instrumentation is handled by the instrument call
- self._instrumentor.instrument()
- return self._create_starlette_app()
-
- def tearDown(self):
- self._instrumentor.uninstrument()
- super().tearDown()
-
-
-class TestAutoInstrumentationLogic(unittest.TestCase):
- def test_instrumentation(self):
- """Verify that instrumentation methods are instrumenting and
- removing as expected.
- """
- instrumentor = otel_starlette.StarletteInstrumentor()
- original = applications.Starlette
- instrumentor.instrument()
- try:
- instrumented = applications.Starlette
- self.assertIsNot(original, instrumented)
- finally:
- instrumentor.uninstrument()
-
- should_be_original = applications.Starlette
- self.assertIs(original, should_be_original)
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-system-metrics/CHANGELOG.md
deleted file mode 100644
index 5f6ff0530c7..00000000000
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/CHANGELOG.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.14b0
-
-Released 2020-10-13
-
-- Fix issue when specific metrics are not available in certain OS
- ([#1207](https://github.com/open-telemetry/opentelemetry-python/pull/1207))
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-system-metrics
- ([#969](https://github.com/open-telemetry/opentelemetry-python/pull/969))
-
-## 0.9b0
-
-Released 2020-06-10
-
-- Initial release (https://github.com/open-telemetry/opentelemetry-python/pull/652)
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/LICENSE b/instrumentation/opentelemetry-instrumentation-system-metrics/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-system-metrics/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-system-metrics/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/README.rst b/instrumentation/opentelemetry-instrumentation-system-metrics/README.rst
deleted file mode 100644
index fc984256bf6..00000000000
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/README.rst
+++ /dev/null
@@ -1,24 +0,0 @@
-OpenTelemetry System Metrics Instrumentation
-============================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-system-metrics.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-system-metrics/
-
-Instrumentation to collect system performance metrics.
-
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-system-metrics
-
-
-References
-----------
-* `OpenTelemetry System Metrics Instrumentation `_
-* `OpenTelemetry Project `_
-
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/setup.cfg b/instrumentation/opentelemetry-instrumentation-system-metrics/setup.cfg
deleted file mode 100644
index f8c27e54d0a..00000000000
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/setup.cfg
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-system-metrics
-description = OpenTelemetry System Metrics Instrumentation
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-system-metrics
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-sdk == 0.16.dev0
- psutil ~= 5.7.0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/setup.py b/instrumentation/opentelemetry-instrumentation-system-metrics/setup.py
deleted file mode 100644
index f0bbf9eff07..00000000000
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "system_metrics",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/__init__.py b/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/__init__.py
deleted file mode 100644
index 2b453dbd7d0..00000000000
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/__init__.py
+++ /dev/null
@@ -1,683 +0,0 @@
-# Copyright The OpenTelemetry 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.
-"""
-Instrument to report system (CPU, memory, network) and
-process (CPU, memory, garbage collection) metrics. By default, the
-following metrics are configured:
-
-.. code:: python
-
- {
- "system.cpu.time": ["idle", "user", "system", "irq"],
- "system.cpu.utilization": ["idle", "user", "system", "irq"],
- "system.memory.usage": ["used", "free", "cached"],
- "system.memory.utilization": ["used", "free", "cached"],
- "system.swap.usage": ["used", "free"],
- "system.swap.utilization": ["used", "free"],
- "system.disk.io": ["read", "write"],
- "system.disk.operations": ["read", "write"],
- "system.disk.time": ["read", "write"],
- "system.disk.merged": ["read", "write"],
- "system.network.dropped.packets": ["transmit", "receive"],
- "system.network.packets": ["transmit", "receive"],
- "system.network.errors": ["transmit", "receive"],
- "system.network.io": ["trasmit", "receive"],
- "system.network.connections": ["family", "type"],
- "runtime.memory": ["rss", "vms"],
- "runtime.cpu.time": ["user", "system"],
- }
-
-Usage
------
-
-.. code:: python
-
- from opentelemetry import metrics
- from opentelemetry.instrumentation.system_metrics import SystemMetrics
- from opentelemetry.sdk.metrics import MeterProvider,
- from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter
-
- metrics.set_meter_provider(MeterProvider())
- exporter = ConsoleMetricsExporter()
- SystemMetrics(exporter)
-
- # metrics are collected asynchronously
- input("...")
-
- # to configure custom metrics
- configuration = {
- "system.memory.usage": ["used", "free", "cached"],
- "system.cpu.time": ["idle", "user", "system", "irq"],
- "system.network.io": ["trasmit", "receive"],
- "runtime.memory": ["rss", "vms"],
- "runtime.cpu.time": ["user", "system"],
- }
- SystemMetrics(exporter, config=configuration)
-
-API
----
-"""
-
-import gc
-import os
-import typing
-from platform import python_implementation
-
-import psutil
-
-from opentelemetry import metrics
-from opentelemetry.sdk.metrics.export import MetricsExporter
-from opentelemetry.sdk.metrics.export.controller import PushController
-from opentelemetry.sdk.util import get_dict_as_key
-
-
-class SystemMetrics:
- # pylint: disable=too-many-statements
- def __init__(
- self,
- exporter: MetricsExporter,
- interval: int = 30,
- labels: typing.Optional[typing.Dict[str, str]] = None,
- config: typing.Optional[typing.Dict[str, typing.List[str]]] = None,
- ):
- self._labels = {} if labels is None else labels
- self.meter = metrics.get_meter(__name__)
- self.controller = PushController(
- meter=self.meter, exporter=exporter, interval=interval
- )
- self._python_implementation = python_implementation().lower()
- if config is None:
- self._config = {
- "system.cpu.time": ["idle", "user", "system", "irq"],
- "system.cpu.utilization": ["idle", "user", "system", "irq"],
- "system.memory.usage": ["used", "free", "cached"],
- "system.memory.utilization": ["used", "free", "cached"],
- "system.swap.usage": ["used", "free"],
- "system.swap.utilization": ["used", "free"],
- # system.swap.page.faults: [],
- # system.swap.page.operations: [],
- "system.disk.io": ["read", "write"],
- "system.disk.operations": ["read", "write"],
- "system.disk.time": ["read", "write"],
- "system.disk.merged": ["read", "write"],
- # "system.filesystem.usage": [],
- # "system.filesystem.utilization": [],
- "system.network.dropped.packets": ["transmit", "receive"],
- "system.network.packets": ["transmit", "receive"],
- "system.network.errors": ["transmit", "receive"],
- "system.network.io": ["trasmit", "receive"],
- "system.network.connections": ["family", "type"],
- "runtime.memory": ["rss", "vms"],
- "runtime.cpu.time": ["user", "system"],
- }
- else:
- self._config = config
-
- self._proc = psutil.Process(os.getpid())
-
- self._system_cpu_time_labels = self._labels.copy()
- self._system_cpu_utilization_labels = self._labels.copy()
-
- self._system_memory_usage_labels = self._labels.copy()
- self._system_memory_utilization_labels = self._labels.copy()
-
- self._system_swap_usage_labels = self._labels.copy()
- self._system_swap_utilization_labels = self._labels.copy()
- # self._system_swap_page_faults = self._labels.copy()
- # self._system_swap_page_operations = self._labels.copy()
-
- self._system_disk_io_labels = self._labels.copy()
- self._system_disk_operations_labels = self._labels.copy()
- self._system_disk_time_labels = self._labels.copy()
- self._system_disk_merged_labels = self._labels.copy()
-
- # self._system_filesystem_usage_labels = self._labels.copy()
- # self._system_filesystem_utilization_labels = self._labels.copy()
-
- self._system_network_dropped_packets_labels = self._labels.copy()
- self._system_network_packets_labels = self._labels.copy()
- self._system_network_errors_labels = self._labels.copy()
- self._system_network_io_labels = self._labels.copy()
- self._system_network_connections_labels = self._labels.copy()
-
- self._runtime_memory_labels = self._labels.copy()
- self._runtime_cpu_time_labels = self._labels.copy()
- self._runtime_gc_count_labels = self._labels.copy()
-
- self.meter.register_sumobserver(
- callback=self._get_system_cpu_time,
- name="system.cpu.time",
- description="System CPU time",
- unit="seconds",
- value_type=float,
- )
-
- self.meter.register_valueobserver(
- callback=self._get_system_cpu_utilization,
- name="system.cpu.utilization",
- description="System CPU utilization",
- unit="1",
- value_type=float,
- )
-
- self.meter.register_valueobserver(
- callback=self._get_system_memory_usage,
- name="system.memory.usage",
- description="System memory usage",
- unit="bytes",
- value_type=int,
- )
-
- self.meter.register_valueobserver(
- callback=self._get_system_memory_utilization,
- name="system.memory.utilization",
- description="System memory utilization",
- unit="1",
- value_type=float,
- )
-
- self.meter.register_valueobserver(
- callback=self._get_system_swap_usage,
- name="system.swap.usage",
- description="System swap usage",
- unit="pages",
- value_type=int,
- )
-
- self.meter.register_valueobserver(
- callback=self._get_system_swap_utilization,
- name="system.swap.utilization",
- description="System swap utilization",
- unit="1",
- value_type=float,
- )
-
- # self.meter.register_sumobserver(
- # callback=self._get_system_swap_page_faults,
- # name="system.swap.page_faults",
- # description="System swap page faults",
- # unit="faults",
- # value_type=int,
- # )
-
- # self.meter.register_sumobserver(
- # callback=self._get_system_swap_page_operations,
- # name="system.swap.page_operations",
- # description="System swap page operations",
- # unit="operations",
- # value_type=int,
- # )
-
- self.meter.register_sumobserver(
- callback=self._get_system_disk_io,
- name="system.disk.io",
- description="System disk IO",
- unit="bytes",
- value_type=int,
- )
-
- self.meter.register_sumobserver(
- callback=self._get_system_disk_operations,
- name="system.disk.operations",
- description="System disk operations",
- unit="operations",
- value_type=int,
- )
-
- self.meter.register_sumobserver(
- callback=self._get_system_disk_time,
- name="system.disk.time",
- description="System disk time",
- unit="seconds",
- value_type=float,
- )
-
- self.meter.register_sumobserver(
- callback=self._get_system_disk_merged,
- name="system.disk.merged",
- description="System disk merged",
- unit="1",
- value_type=int,
- )
-
- # self.meter.register_valueobserver(
- # callback=self._get_system_filesystem_usage,
- # name="system.filesystem.usage",
- # description="System filesystem usage",
- # unit="bytes",
- # value_type=int,
- # )
-
- # self.meter.register_valueobserver(
- # callback=self._get_system_filesystem_utilization,
- # name="system.filesystem.utilization",
- # description="System filesystem utilization",
- # unit="1",
- # value_type=float,
- # )
-
- self.meter.register_sumobserver(
- callback=self._get_system_network_dropped_packets,
- name="system.network.dropped_packets",
- description="System network dropped_packets",
- unit="packets",
- value_type=int,
- )
-
- self.meter.register_sumobserver(
- callback=self._get_system_network_packets,
- name="system.network.packets",
- description="System network packets",
- unit="packets",
- value_type=int,
- )
-
- self.meter.register_sumobserver(
- callback=self._get_system_network_errors,
- name="system.network.errors",
- description="System network errors",
- unit="errors",
- value_type=int,
- )
-
- self.meter.register_sumobserver(
- callback=self._get_system_network_io,
- name="system.network.io",
- description="System network io",
- unit="bytes",
- value_type=int,
- )
-
- self.meter.register_updownsumobserver(
- callback=self._get_system_network_connections,
- name="system.network.connections",
- description="System network connections",
- unit="connections",
- value_type=int,
- )
-
- self.meter.register_sumobserver(
- callback=self._get_runtime_memory,
- name="runtime.{}.memory".format(self._python_implementation),
- description="Runtime {} memory".format(
- self._python_implementation
- ),
- unit="bytes",
- value_type=int,
- )
-
- self.meter.register_sumobserver(
- callback=self._get_runtime_cpu_time,
- name="runtime.{}.cpu_time".format(self._python_implementation),
- description="Runtime {} CPU time".format(
- self._python_implementation
- ),
- unit="seconds",
- value_type=float,
- )
-
- self.meter.register_sumobserver(
- callback=self._get_runtime_gc_count,
- name="runtime.{}.gc_count".format(self._python_implementation),
- description="Runtime {} GC count".format(
- self._python_implementation
- ),
- unit="bytes",
- value_type=int,
- )
-
- def _get_system_cpu_time(self, observer: metrics.ValueObserver) -> None:
- """Observer callback for system CPU time
-
- Args:
- observer: the observer to update
- """
- for cpu, times in enumerate(psutil.cpu_times(percpu=True)):
- for metric in self._config["system.cpu.time"]:
- if hasattr(times, metric):
- self._system_cpu_time_labels["state"] = metric
- self._system_cpu_time_labels["cpu"] = cpu + 1
- observer.observe(
- getattr(times, metric), self._system_cpu_time_labels
- )
-
- def _get_system_cpu_utilization(
- self, observer: metrics.ValueObserver
- ) -> None:
- """Observer callback for system CPU utilization
-
- Args:
- observer: the observer to update
- """
-
- for cpu, times_percent in enumerate(
- psutil.cpu_times_percent(percpu=True)
- ):
- for metric in self._config["system.cpu.utilization"]:
- if hasattr(times_percent, metric):
- self._system_cpu_utilization_labels["state"] = metric
- self._system_cpu_utilization_labels["cpu"] = cpu + 1
- observer.observe(
- getattr(times_percent, metric) / 100,
- self._system_cpu_utilization_labels,
- )
-
- def _get_system_memory_usage(
- self, observer: metrics.ValueObserver
- ) -> None:
- """Observer callback for memory usage
-
- Args:
- observer: the observer to update
- """
- virtual_memory = psutil.virtual_memory()
- for metric in self._config["system.memory.usage"]:
- self._system_memory_usage_labels["state"] = metric
- if hasattr(virtual_memory, metric):
- observer.observe(
- getattr(virtual_memory, metric),
- self._system_memory_usage_labels,
- )
-
- def _get_system_memory_utilization(
- self, observer: metrics.ValueObserver
- ) -> None:
- """Observer callback for memory utilization
-
- Args:
- observer: the observer to update
- """
- system_memory = psutil.virtual_memory()
-
- for metric in self._config["system.memory.utilization"]:
- self._system_memory_utilization_labels["state"] = metric
- if hasattr(system_memory, metric):
- observer.observe(
- getattr(system_memory, metric) / system_memory.total,
- self._system_memory_utilization_labels,
- )
-
- def _get_system_swap_usage(self, observer: metrics.ValueObserver) -> None:
- """Observer callback for swap usage
-
- Args:
- observer: the observer to update
- """
- system_swap = psutil.swap_memory()
-
- for metric in self._config["system.swap.usage"]:
- self._system_swap_usage_labels["state"] = metric
- if hasattr(system_swap, metric):
- observer.observe(
- getattr(system_swap, metric),
- self._system_swap_usage_labels,
- )
-
- def _get_system_swap_utilization(
- self, observer: metrics.ValueObserver
- ) -> None:
- """Observer callback for swap utilization
-
- Args:
- observer: the observer to update
- """
- system_swap = psutil.swap_memory()
-
- for metric in self._config["system.swap.utilization"]:
- if hasattr(system_swap, metric):
- self._system_swap_utilization_labels["state"] = metric
- observer.observe(
- getattr(system_swap, metric) / system_swap.total,
- self._system_swap_utilization_labels,
- )
-
- # TODO Add _get_system_swap_page_faults
- # TODO Add _get_system_swap_page_operations
-
- def _get_system_disk_io(self, observer: metrics.SumObserver) -> None:
- """Observer callback for disk IO
-
- Args:
- observer: the observer to update
- """
- for device, counters in psutil.disk_io_counters(perdisk=True).items():
- for metric in self._config["system.disk.io"]:
- if hasattr(counters, "{}_bytes".format(metric)):
- self._system_disk_io_labels["device"] = device
- self._system_disk_io_labels["direction"] = metric
- observer.observe(
- getattr(counters, "{}_bytes".format(metric)),
- self._system_disk_io_labels,
- )
-
- def _get_system_disk_operations(
- self, observer: metrics.SumObserver
- ) -> None:
- """Observer callback for disk operations
-
- Args:
- observer: the observer to update
- """
- for device, counters in psutil.disk_io_counters(perdisk=True).items():
- for metric in self._config["system.disk.operations"]:
- if hasattr(counters, "{}_count".format(metric)):
- self._system_disk_operations_labels["device"] = device
- self._system_disk_operations_labels["direction"] = metric
- observer.observe(
- getattr(counters, "{}_count".format(metric)),
- self._system_disk_operations_labels,
- )
-
- def _get_system_disk_time(self, observer: metrics.SumObserver) -> None:
- """Observer callback for disk time
-
- Args:
- observer: the observer to update
- """
- for device, counters in psutil.disk_io_counters(perdisk=True).items():
- for metric in self._config["system.disk.time"]:
- if hasattr(counters, "{}_time".format(metric)):
- self._system_disk_time_labels["device"] = device
- self._system_disk_time_labels["direction"] = metric
- observer.observe(
- getattr(counters, "{}_time".format(metric)) / 1000,
- self._system_disk_time_labels,
- )
-
- def _get_system_disk_merged(self, observer: metrics.SumObserver) -> None:
- """Observer callback for disk merged operations
-
- Args:
- observer: the observer to update
- """
-
- # FIXME The units in the spec is 1, it seems like it should be
- # operations or the value type should be Double
-
- for device, counters in psutil.disk_io_counters(perdisk=True).items():
- for metric in self._config["system.disk.time"]:
- if hasattr(counters, "{}_merged_count".format(metric)):
- self._system_disk_merged_labels["device"] = device
- self._system_disk_merged_labels["direction"] = metric
- observer.observe(
- getattr(counters, "{}_merged_count".format(metric)),
- self._system_disk_merged_labels,
- )
-
- # TODO Add _get_system_filesystem_usage
- # TODO Add _get_system_filesystem_utilization
- # TODO Filesystem information can be obtained with os.statvfs in Unix-like
- # OSs, how to do the same in Windows?
-
- def _get_system_network_dropped_packets(
- self, observer: metrics.SumObserver
- ) -> None:
- """Observer callback for network dropped packets
-
- Args:
- observer: the observer to update
- """
-
- for device, counters in psutil.net_io_counters(pernic=True).items():
- for metric in self._config["system.network.dropped.packets"]:
- in_out = {"receive": "in", "transmit": "out"}[metric]
- if hasattr(counters, "drop{}".format(in_out)):
- self._system_network_dropped_packets_labels[
- "device"
- ] = device
- self._system_network_dropped_packets_labels[
- "direction"
- ] = metric
- observer.observe(
- getattr(counters, "drop{}".format(in_out)),
- self._system_network_dropped_packets_labels,
- )
-
- def _get_system_network_packets(
- self, observer: metrics.SumObserver
- ) -> None:
- """Observer callback for network packets
-
- Args:
- observer: the observer to update
- """
-
- for device, counters in psutil.net_io_counters(pernic=True).items():
- for metric in self._config["system.network.dropped.packets"]:
- recv_sent = {"receive": "recv", "transmit": "sent"}[metric]
- if hasattr(counters, "packets_{}".format(recv_sent)):
- self._system_network_packets_labels["device"] = device
- self._system_network_packets_labels["direction"] = metric
- observer.observe(
- getattr(counters, "packets_{}".format(recv_sent)),
- self._system_network_packets_labels,
- )
-
- def _get_system_network_errors(
- self, observer: metrics.SumObserver
- ) -> None:
- """Observer callback for network errors
-
- Args:
- observer: the observer to update
- """
- for device, counters in psutil.net_io_counters(pernic=True).items():
- for metric in self._config["system.network.errors"]:
- in_out = {"receive": "in", "transmit": "out"}[metric]
- if hasattr(counters, "err{}".format(in_out)):
- self._system_network_errors_labels["device"] = device
- self._system_network_errors_labels["direction"] = metric
- observer.observe(
- getattr(counters, "err{}".format(in_out)),
- self._system_network_errors_labels,
- )
-
- def _get_system_network_io(self, observer: metrics.SumObserver) -> None:
- """Observer callback for network IO
-
- Args:
- observer: the observer to update
- """
-
- for device, counters in psutil.net_io_counters(pernic=True).items():
- for metric in self._config["system.network.dropped.packets"]:
- recv_sent = {"receive": "recv", "transmit": "sent"}[metric]
- if hasattr(counters, "bytes_{}".format(recv_sent)):
- self._system_network_io_labels["device"] = device
- self._system_network_io_labels["direction"] = metric
- observer.observe(
- getattr(counters, "bytes_{}".format(recv_sent)),
- self._system_network_io_labels,
- )
-
- def _get_system_network_connections(
- self, observer: metrics.UpDownSumObserver
- ) -> None:
- """Observer callback for network connections
-
- Args:
- observer: the observer to update
- """
- # TODO How to find the device identifier for a particular
- # connection?
-
- connection_counters = {}
-
- for net_connection in psutil.net_connections():
- for metric in self._config["system.network.connections"]:
- self._system_network_connections_labels["protocol"] = {
- 1: "tcp",
- 2: "udp",
- }[net_connection.type.value]
- self._system_network_connections_labels[
- "state"
- ] = net_connection.status
- self._system_network_connections_labels[metric] = getattr(
- net_connection, metric
- )
-
- connection_counters_key = get_dict_as_key(
- self._system_network_connections_labels
- )
-
- if connection_counters_key in connection_counters.keys():
- connection_counters[connection_counters_key]["counter"] += 1
- else:
- connection_counters[connection_counters_key] = {
- "counter": 1,
- "labels": self._system_network_connections_labels.copy(),
- }
-
- for connection_counter in connection_counters.values():
- observer.observe(
- connection_counter["counter"], connection_counter["labels"],
- )
-
- def _get_runtime_memory(self, observer: metrics.SumObserver) -> None:
- """Observer callback for runtime memory
-
- Args:
- observer: the observer to update
- """
- proc_memory = self._proc.memory_info()
- for metric in self._config["runtime.memory"]:
- if hasattr(proc_memory, metric):
- self._runtime_memory_labels["type"] = metric
- observer.observe(
- getattr(proc_memory, metric), self._runtime_memory_labels,
- )
-
- def _get_runtime_cpu_time(self, observer: metrics.SumObserver) -> None:
- """Observer callback for runtime CPU time
-
- Args:
- observer: the observer to update
- """
- proc_cpu = self._proc.cpu_times()
- for metric in self._config["runtime.cpu.time"]:
- if hasattr(proc_cpu, metric):
- self._runtime_cpu_time_labels["type"] = metric
- observer.observe(
- getattr(proc_cpu, metric), self._runtime_cpu_time_labels,
- )
-
- def _get_runtime_gc_count(self, observer: metrics.SumObserver) -> None:
- """Observer callback for garbage collection
-
- Args:
- observer: the observer to update
- """
- for index, count in enumerate(gc.get_count()):
- self._runtime_gc_count_labels["count"] = str(index)
- observer.observe(count, self._runtime_gc_count_labels)
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/version.py b/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-system-metrics/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/tests/test_system_metrics.py b/instrumentation/opentelemetry-instrumentation-system-metrics/tests/test_system_metrics.py
deleted file mode 100644
index 2f155383f46..00000000000
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/tests/test_system_metrics.py
+++ /dev/null
@@ -1,703 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-# pylint: disable=protected-access
-
-from collections import namedtuple
-from platform import python_implementation
-from unittest import mock
-
-from opentelemetry import metrics
-from opentelemetry.instrumentation.system_metrics import SystemMetrics
-from opentelemetry.sdk.metrics.export.aggregate import ValueObserverAggregator
-from opentelemetry.test.test_base import TestBase
-
-
-class TestSystemMetrics(TestBase):
- def setUp(self):
- super().setUp()
- self.memory_metrics_exporter.clear()
- self.implementation = python_implementation().lower()
-
- def test_system_metrics_constructor(self):
- # ensure the observers have been registered
- meter = metrics.get_meter(__name__)
- with mock.patch("opentelemetry.metrics.get_meter") as mock_get_meter:
- mock_get_meter.return_value = meter
- SystemMetrics(self.memory_metrics_exporter)
-
- self.assertEqual(len(meter.observers), 18)
-
- observer_names = [
- "system.cpu.time",
- "system.cpu.utilization",
- "system.memory.usage",
- "system.memory.utilization",
- "system.swap.usage",
- "system.swap.utilization",
- "system.disk.io",
- "system.disk.operations",
- "system.disk.time",
- "system.disk.merged",
- "system.network.dropped_packets",
- "system.network.packets",
- "system.network.errors",
- "system.network.io",
- "system.network.connections",
- "runtime.{}.memory".format(self.implementation),
- "runtime.{}.cpu_time".format(self.implementation),
- "runtime.{}.gc_count".format(self.implementation),
- ]
-
- for observer in meter.observers:
- self.assertIn(observer.name, observer_names)
- observer_names.remove(observer.name)
-
- def _assert_metrics(self, observer_name, system_metrics, expected):
- system_metrics.controller.tick()
- assertions = 0
- for (
- metric
- ) in (
- self.memory_metrics_exporter._exported_metrics # pylint: disable=protected-access
- ):
- if (
- metric.labels in expected
- and metric.instrument.name == observer_name
- ):
- self.assertEqual(
- metric.aggregator.checkpoint, expected[metric.labels],
- )
- assertions += 1
- self.assertEqual(len(expected), assertions)
-
- def _test_metrics(self, observer_name, expected):
- meter = self.meter_provider.get_meter(__name__)
-
- with mock.patch("opentelemetry.metrics.get_meter") as mock_get_meter:
- mock_get_meter.return_value = meter
- system_metrics = SystemMetrics(self.memory_metrics_exporter)
- self._assert_metrics(observer_name, system_metrics, expected)
-
- # When this test case is executed, _get_system_cpu_utilization gets run
- # too because of the controller thread which runs all observers. This patch
- # is added here to stop a warning that would otherwise be raised.
- # pylint: disable=unused-argument
- @mock.patch("psutil.cpu_times_percent")
- @mock.patch("psutil.cpu_times")
- def test_system_cpu_time(self, mock_cpu_times, mock_cpu_times_percent):
- CPUTimes = namedtuple("CPUTimes", ["idle", "user", "system", "irq"])
- mock_cpu_times.return_value = [
- CPUTimes(idle=1.2, user=3.4, system=5.6, irq=7.8),
- CPUTimes(idle=1.2, user=3.4, system=5.6, irq=7.8),
- ]
-
- expected = {
- (("cpu", 1), ("state", "idle"),): 1.2,
- (("cpu", 1), ("state", "user"),): 3.4,
- (("cpu", 1), ("state", "system"),): 5.6,
- (("cpu", 1), ("state", "irq"),): 7.8,
- (("cpu", 2), ("state", "idle"),): 1.2,
- (("cpu", 2), ("state", "user"),): 3.4,
- (("cpu", 2), ("state", "system"),): 5.6,
- (("cpu", 2), ("state", "irq"),): 7.8,
- }
- self._test_metrics("system.cpu.time", expected)
-
- @mock.patch("psutil.cpu_times_percent")
- def test_system_cpu_utilization(self, mock_cpu_times_percent):
- CPUTimesPercent = namedtuple(
- "CPUTimesPercent", ["idle", "user", "system", "irq"]
- )
- mock_cpu_times_percent.return_value = [
- CPUTimesPercent(idle=1.2, user=3.4, system=5.6, irq=7.8),
- CPUTimesPercent(idle=1.2, user=3.4, system=5.6, irq=7.8),
- ]
-
- expected = {
- (("cpu", 1), ("state", "idle"),): ValueObserverAggregator._TYPE(
- min=1.2 / 100,
- max=1.2 / 100,
- sum=1.2 / 100,
- count=1,
- last=1.2 / 100,
- ),
- (("cpu", 1), ("state", "user"),): ValueObserverAggregator._TYPE(
- min=3.4 / 100,
- max=3.4 / 100,
- sum=3.4 / 100,
- count=1,
- last=3.4 / 100,
- ),
- (("cpu", 1), ("state", "system"),): ValueObserverAggregator._TYPE(
- min=5.6 / 100,
- max=5.6 / 100,
- sum=5.6 / 100,
- count=1,
- last=5.6 / 100,
- ),
- (("cpu", 1), ("state", "irq"),): ValueObserverAggregator._TYPE(
- min=7.8 / 100,
- max=7.8 / 100,
- sum=7.8 / 100,
- count=1,
- last=7.8 / 100,
- ),
- (("cpu", 2), ("state", "idle"),): ValueObserverAggregator._TYPE(
- min=1.2 / 100,
- max=1.2 / 100,
- sum=1.2 / 100,
- count=1,
- last=1.2 / 100,
- ),
- (("cpu", 2), ("state", "user"),): ValueObserverAggregator._TYPE(
- min=3.4 / 100,
- max=3.4 / 100,
- sum=3.4 / 100,
- count=1,
- last=3.4 / 100,
- ),
- (("cpu", 2), ("state", "system"),): ValueObserverAggregator._TYPE(
- min=5.6 / 100,
- max=5.6 / 100,
- sum=5.6 / 100,
- count=1,
- last=5.6 / 100,
- ),
- (("cpu", 2), ("state", "irq"),): ValueObserverAggregator._TYPE(
- min=7.8 / 100,
- max=7.8 / 100,
- sum=7.8 / 100,
- count=1,
- last=7.8 / 100,
- ),
- }
- self._test_metrics("system.cpu.utilization", expected)
-
- @mock.patch("psutil.virtual_memory")
- def test_system_memory_usage(self, mock_virtual_memory):
- VirtualMemory = namedtuple(
- "VirtualMemory", ["used", "free", "cached", "total"]
- )
- mock_virtual_memory.return_value = VirtualMemory(
- used=1, free=2, cached=3, total=4
- )
-
- expected = {
- (("state", "used"),): ValueObserverAggregator._TYPE(
- min=1, max=1, sum=1, count=1, last=1
- ),
- (("state", "free"),): ValueObserverAggregator._TYPE(
- min=2, max=2, sum=2, count=1, last=2
- ),
- (("state", "cached"),): ValueObserverAggregator._TYPE(
- min=3, max=3, sum=3, count=1, last=3
- ),
- }
- self._test_metrics("system.memory.usage", expected)
-
- @mock.patch("psutil.virtual_memory")
- def test_system_memory_utilization(self, mock_virtual_memory):
- VirtualMemory = namedtuple(
- "VirtualMemory", ["used", "free", "cached", "total"]
- )
- mock_virtual_memory.return_value = VirtualMemory(
- used=1, free=2, cached=3, total=4
- )
-
- expected = {
- (("state", "used"),): ValueObserverAggregator._TYPE(
- min=1 / 4, max=1 / 4, sum=1 / 4, count=1, last=1 / 4
- ),
- (("state", "free"),): ValueObserverAggregator._TYPE(
- min=2 / 4, max=2 / 4, sum=2 / 4, count=1, last=2 / 4
- ),
- (("state", "cached"),): ValueObserverAggregator._TYPE(
- min=3 / 4, max=3 / 4, sum=3 / 4, count=1, last=3 / 4
- ),
- }
- self._test_metrics("system.memory.utilization", expected)
-
- @mock.patch("psutil.swap_memory")
- def test_system_swap_usage(self, mock_swap_memory):
- SwapMemory = namedtuple("SwapMemory", ["used", "free", "total"])
- mock_swap_memory.return_value = SwapMemory(used=1, free=2, total=3)
-
- expected = {
- (("state", "used"),): ValueObserverAggregator._TYPE(
- min=1, max=1, sum=1, count=1, last=1
- ),
- (("state", "free"),): ValueObserverAggregator._TYPE(
- min=2, max=2, sum=2, count=1, last=2
- ),
- }
- self._test_metrics("system.swap.usage", expected)
-
- @mock.patch("psutil.swap_memory")
- def test_system_swap_utilization(self, mock_swap_memory):
- SwapMemory = namedtuple("SwapMemory", ["used", "free", "total"])
- mock_swap_memory.return_value = SwapMemory(used=1, free=2, total=3)
-
- expected = {
- (("state", "used"),): ValueObserverAggregator._TYPE(
- min=1 / 3, max=1 / 3, sum=1 / 3, count=1, last=1 / 3
- ),
- (("state", "free"),): ValueObserverAggregator._TYPE(
- min=2 / 3, max=2 / 3, sum=2 / 3, count=1, last=2 / 3
- ),
- }
- self._test_metrics("system.swap.utilization", expected)
-
- @mock.patch("psutil.disk_io_counters")
- def test_system_disk_io(self, mock_disk_io_counters):
- DiskIO = namedtuple(
- "DiskIO",
- [
- "read_count",
- "write_count",
- "read_bytes",
- "write_bytes",
- "read_time",
- "write_time",
- "read_merged_count",
- "write_merged_count",
- ],
- )
- mock_disk_io_counters.return_value = {
- "sda": DiskIO(
- read_count=1,
- write_count=2,
- read_bytes=3,
- write_bytes=4,
- read_time=5,
- write_time=6,
- read_merged_count=7,
- write_merged_count=8,
- ),
- "sdb": DiskIO(
- read_count=9,
- write_count=10,
- read_bytes=11,
- write_bytes=12,
- read_time=13,
- write_time=14,
- read_merged_count=15,
- write_merged_count=16,
- ),
- }
-
- expected = {
- (("device", "sda"), ("direction", "read"),): 3,
- (("device", "sda"), ("direction", "write"),): 4,
- (("device", "sdb"), ("direction", "read"),): 11,
- (("device", "sdb"), ("direction", "write"),): 12,
- }
- self._test_metrics("system.disk.io", expected)
-
- @mock.patch("psutil.disk_io_counters")
- def test_system_disk_operations(self, mock_disk_io_counters):
- DiskIO = namedtuple(
- "DiskIO",
- [
- "read_count",
- "write_count",
- "read_bytes",
- "write_bytes",
- "read_time",
- "write_time",
- "read_merged_count",
- "write_merged_count",
- ],
- )
- mock_disk_io_counters.return_value = {
- "sda": DiskIO(
- read_count=1,
- write_count=2,
- read_bytes=3,
- write_bytes=4,
- read_time=5,
- write_time=6,
- read_merged_count=7,
- write_merged_count=8,
- ),
- "sdb": DiskIO(
- read_count=9,
- write_count=10,
- read_bytes=11,
- write_bytes=12,
- read_time=13,
- write_time=14,
- read_merged_count=15,
- write_merged_count=16,
- ),
- }
-
- expected = {
- (("device", "sda"), ("direction", "read"),): 1,
- (("device", "sda"), ("direction", "write"),): 2,
- (("device", "sdb"), ("direction", "read"),): 9,
- (("device", "sdb"), ("direction", "write"),): 10,
- }
- self._test_metrics("system.disk.operations", expected)
-
- @mock.patch("psutil.disk_io_counters")
- def test_system_disk_time(self, mock_disk_io_counters):
- DiskIO = namedtuple(
- "DiskIO",
- [
- "read_count",
- "write_count",
- "read_bytes",
- "write_bytes",
- "read_time",
- "write_time",
- "read_merged_count",
- "write_merged_count",
- ],
- )
- mock_disk_io_counters.return_value = {
- "sda": DiskIO(
- read_count=1,
- write_count=2,
- read_bytes=3,
- write_bytes=4,
- read_time=5,
- write_time=6,
- read_merged_count=7,
- write_merged_count=8,
- ),
- "sdb": DiskIO(
- read_count=9,
- write_count=10,
- read_bytes=11,
- write_bytes=12,
- read_time=13,
- write_time=14,
- read_merged_count=15,
- write_merged_count=16,
- ),
- }
-
- expected = {
- (("device", "sda"), ("direction", "read"),): 5 / 1000,
- (("device", "sda"), ("direction", "write"),): 6 / 1000,
- (("device", "sdb"), ("direction", "read"),): 13 / 1000,
- (("device", "sdb"), ("direction", "write"),): 14 / 1000,
- }
- self._test_metrics("system.disk.time", expected)
-
- @mock.patch("psutil.disk_io_counters")
- def test_system_disk_merged(self, mock_disk_io_counters):
- DiskIO = namedtuple(
- "DiskIO",
- [
- "read_count",
- "write_count",
- "read_bytes",
- "write_bytes",
- "read_time",
- "write_time",
- "read_merged_count",
- "write_merged_count",
- ],
- )
- mock_disk_io_counters.return_value = {
- "sda": DiskIO(
- read_count=1,
- write_count=2,
- read_bytes=3,
- write_bytes=4,
- read_time=5,
- write_time=6,
- read_merged_count=7,
- write_merged_count=8,
- ),
- "sdb": DiskIO(
- read_count=9,
- write_count=10,
- read_bytes=11,
- write_bytes=12,
- read_time=13,
- write_time=14,
- read_merged_count=15,
- write_merged_count=16,
- ),
- }
-
- expected = {
- (("device", "sda"), ("direction", "read"),): 7,
- (("device", "sda"), ("direction", "write"),): 8,
- (("device", "sdb"), ("direction", "read"),): 15,
- (("device", "sdb"), ("direction", "write"),): 16,
- }
- self._test_metrics("system.disk.merged", expected)
-
- @mock.patch("psutil.net_io_counters")
- def test_system_network_dropped_packets(self, mock_net_io_counters):
- NetIO = namedtuple(
- "NetIO",
- [
- "dropin",
- "dropout",
- "packets_sent",
- "packets_recv",
- "errin",
- "errout",
- "bytes_sent",
- "bytes_recv",
- ],
- )
- mock_net_io_counters.return_value = {
- "eth0": NetIO(
- dropin=1,
- dropout=2,
- packets_sent=3,
- packets_recv=4,
- errin=5,
- errout=6,
- bytes_sent=7,
- bytes_recv=8,
- ),
- "eth1": NetIO(
- dropin=9,
- dropout=10,
- packets_sent=11,
- packets_recv=12,
- errin=13,
- errout=14,
- bytes_sent=15,
- bytes_recv=16,
- ),
- }
-
- expected = {
- (("device", "eth0"), ("direction", "receive"),): 1,
- (("device", "eth0"), ("direction", "transmit"),): 2,
- (("device", "eth1"), ("direction", "receive"),): 9,
- (("device", "eth1"), ("direction", "transmit"),): 10,
- }
- self._test_metrics("system.network.dropped_packets", expected)
-
- @mock.patch("psutil.net_io_counters")
- def test_system_network_packets(self, mock_net_io_counters):
- NetIO = namedtuple(
- "NetIO",
- [
- "dropin",
- "dropout",
- "packets_sent",
- "packets_recv",
- "errin",
- "errout",
- "bytes_sent",
- "bytes_recv",
- ],
- )
- mock_net_io_counters.return_value = {
- "eth0": NetIO(
- dropin=1,
- dropout=2,
- packets_sent=3,
- packets_recv=4,
- errin=5,
- errout=6,
- bytes_sent=7,
- bytes_recv=8,
- ),
- "eth1": NetIO(
- dropin=9,
- dropout=10,
- packets_sent=11,
- packets_recv=12,
- errin=13,
- errout=14,
- bytes_sent=15,
- bytes_recv=16,
- ),
- }
-
- expected = {
- (("device", "eth0"), ("direction", "receive"),): 4,
- (("device", "eth0"), ("direction", "transmit"),): 3,
- (("device", "eth1"), ("direction", "receive"),): 12,
- (("device", "eth1"), ("direction", "transmit"),): 11,
- }
- self._test_metrics("system.network.packets", expected)
-
- @mock.patch("psutil.net_io_counters")
- def test_system_network_errors(self, mock_net_io_counters):
- NetIO = namedtuple(
- "NetIO",
- [
- "dropin",
- "dropout",
- "packets_sent",
- "packets_recv",
- "errin",
- "errout",
- "bytes_sent",
- "bytes_recv",
- ],
- )
- mock_net_io_counters.return_value = {
- "eth0": NetIO(
- dropin=1,
- dropout=2,
- packets_sent=3,
- packets_recv=4,
- errin=5,
- errout=6,
- bytes_sent=7,
- bytes_recv=8,
- ),
- "eth1": NetIO(
- dropin=9,
- dropout=10,
- packets_sent=11,
- packets_recv=12,
- errin=13,
- errout=14,
- bytes_sent=15,
- bytes_recv=16,
- ),
- }
-
- expected = {
- (("device", "eth0"), ("direction", "receive"),): 5,
- (("device", "eth0"), ("direction", "transmit"),): 6,
- (("device", "eth1"), ("direction", "receive"),): 13,
- (("device", "eth1"), ("direction", "transmit"),): 14,
- }
- self._test_metrics("system.network.errors", expected)
-
- @mock.patch("psutil.net_io_counters")
- def test_system_network_io(self, mock_net_io_counters):
- NetIO = namedtuple(
- "NetIO",
- [
- "dropin",
- "dropout",
- "packets_sent",
- "packets_recv",
- "errin",
- "errout",
- "bytes_sent",
- "bytes_recv",
- ],
- )
- mock_net_io_counters.return_value = {
- "eth0": NetIO(
- dropin=1,
- dropout=2,
- packets_sent=3,
- packets_recv=4,
- errin=5,
- errout=6,
- bytes_sent=7,
- bytes_recv=8,
- ),
- "eth1": NetIO(
- dropin=9,
- dropout=10,
- packets_sent=11,
- packets_recv=12,
- errin=13,
- errout=14,
- bytes_sent=15,
- bytes_recv=16,
- ),
- }
-
- expected = {
- (("device", "eth0"), ("direction", "receive"),): 8,
- (("device", "eth0"), ("direction", "transmit"),): 7,
- (("device", "eth1"), ("direction", "receive"),): 16,
- (("device", "eth1"), ("direction", "transmit"),): 15,
- }
- self._test_metrics("system.network.io", expected)
-
- @mock.patch("psutil.net_connections")
- def test_system_network_connections(self, mock_net_connections):
- NetConnection = namedtuple(
- "NetworkConnection", ["family", "type", "status"]
- )
- Type = namedtuple("Type", ["value"])
- mock_net_connections.return_value = [
- NetConnection(family=1, status="ESTABLISHED", type=Type(value=2),),
- NetConnection(family=1, status="ESTABLISHED", type=Type(value=1),),
- ]
-
- expected = {
- (
- ("family", 1),
- ("protocol", "udp"),
- ("state", "ESTABLISHED"),
- ("type", Type(value=2)),
- ): 1,
- (
- ("family", 1),
- ("protocol", "tcp"),
- ("state", "ESTABLISHED"),
- ("type", Type(value=1)),
- ): 1,
- }
- self._test_metrics("system.network.connections", expected)
-
- @mock.patch("psutil.Process.memory_info")
- def test_runtime_memory(self, mock_process_memory_info):
-
- PMem = namedtuple("PMem", ["rss", "vms"])
-
- mock_process_memory_info.configure_mock(
- **{"return_value": PMem(rss=1, vms=2)}
- )
-
- expected = {
- (("type", "rss"),): 1,
- (("type", "vms"),): 2,
- }
- self._test_metrics(
- "runtime.{}.memory".format(self.implementation), expected
- )
-
- @mock.patch("psutil.Process.cpu_times")
- def test_runtime_cpu_time(self, mock_process_cpu_times):
-
- PCPUTimes = namedtuple("PCPUTimes", ["user", "system"])
-
- mock_process_cpu_times.configure_mock(
- **{"return_value": PCPUTimes(user=1.1, system=2.2)}
- )
-
- expected = {
- (("type", "user"),): 1.1,
- (("type", "system"),): 2.2,
- }
- self._test_metrics(
- "runtime.{}.cpu_time".format(self.implementation), expected
- )
-
- @mock.patch("gc.get_count")
- def test_runtime_get_count(self, mock_gc_get_count):
-
- mock_gc_get_count.configure_mock(**{"return_value": (1, 2, 3)})
-
- expected = {
- (("count", "0"),): 1,
- (("count", "1"),): 2,
- (("count", "2"),): 3,
- }
- self._test_metrics(
- "runtime.{}.gc_count".format(self.implementation), expected
- )
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-tornado/CHANGELOG.md
deleted file mode 100644
index e341a1f5a39..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/CHANGELOG.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.14b0
-
-Released 2020-10-13
-
-- Added support for `OTEL_PYTHON_TORNADO_TRACED_REQUEST_ATTRS` ([#1178](https://github.com/open-telemetry/opentelemetry-python/pull/1178))
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Initial release. Supports Tornado 6.x on Python 3.5 and newer.
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/LICENSE b/instrumentation/opentelemetry-instrumentation-tornado/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-tornado/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-tornado/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/README.rst b/instrumentation/opentelemetry-instrumentation-tornado/README.rst
deleted file mode 100644
index 088c7f0e85d..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/README.rst
+++ /dev/null
@@ -1,51 +0,0 @@
-OpenTelemetry Tornado Instrumentation
-======================================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-tornado.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-tornado/
-
-This library builds on the OpenTelemetry WSGI middleware to track web requests
-in Tornado applications.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-tornado
-
-Configuration
--------------
-
-The following environment variables are supported as configuration options:
-
-- OTEL_PYTHON_TORNADO_EXCLUDED_URLS
-
-A comma separated list of paths that should not be automatically traced. For example, if this is set to
-
-::
-
- export OTEL_PYTHON_TORNADO_EXLUDED_URLS='/healthz,/ping'
-
-Then any requests made to ``/healthz`` and ``/ping`` will not be automatically traced.
-
-Request attributes
-********************
-To extract certain attributes from Tornado's request object and use them as span attributes, set the environment variable ``OTEL_PYTHON_TORNADO_TRACED_REQUEST_ATTRS`` to a comma
-delimited list of request attribute names.
-
-For example,
-
-::
-
- export OTEL_PYTHON_TORNADO_TRACED_REQUEST_ATTRS='uri,query'
-
-will extract path_info and content_type attributes from every traced request and add them as span attributes.
-
-References
-----------
-
-* `OpenTelemetry Tornado Instrumentation `_
-* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg b/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg
deleted file mode 100644
index 889eb0e97c3..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-tornado
-description = Tornado instrumentation for OpenTelemetry
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-tornado
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- tornado >= 6.0
- opentelemetry-instrumentation == 0.16.dev0
- opentelemetry-api == 0.16.dev0
-
-[options.extras_require]
-test =
- tornado >= 6.0
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/setup.py b/instrumentation/opentelemetry-instrumentation-tornado/setup.py
deleted file mode 100644
index bd6814b50ee..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/setup.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR,
- "src",
- "opentelemetry",
- "instrumentation",
- "tornado",
- "version.py",
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(
- version=PACKAGE_INFO["__version__"],
- entry_points={
- "opentelemetry_instrumentor": [
- "tornado = opentelemetry.instrumentation.tornado:TornadoInstrumentor"
- ]
- },
-)
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py
deleted file mode 100644
index 6bb956ecb58..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py
+++ /dev/null
@@ -1,273 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-"""
-This library uses OpenTelemetry to track web requests in Tornado applications.
-
-Usage
------
-
-.. code-block:: python
-
- import tornado.web
- from opentelemetry.instrumentation.tornado import TornadoInstrumentor
-
- # apply tornado instrumentation
- TornadoInstrumentor().instrument()
-
- class Handler(tornado.web.RequestHandler):
- def get(self):
- self.set_status(200)
-
- app = tornado.web.Application([(r"/", Handler)])
- app.listen(8080)
- tornado.ioloop.IOLoop.current().start()
-"""
-
-import inspect
-import typing
-from collections import namedtuple
-from functools import partial, wraps
-from logging import getLogger
-
-import tornado.web
-import wrapt
-from tornado.routing import Rule
-from wrapt import wrap_function_wrapper
-
-from opentelemetry import configuration, context, propagators, trace
-from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
-from opentelemetry.instrumentation.tornado.version import __version__
-from opentelemetry.instrumentation.utils import (
- extract_attributes_from_object,
- http_status_to_status_code,
- unwrap,
-)
-from opentelemetry.trace.propagation.textmap import DictGetter
-from opentelemetry.trace.status import Status
-from opentelemetry.util import ExcludeList, time_ns
-
-from .client import fetch_async # pylint: disable=E0401
-
-_logger = getLogger(__name__)
-_TraceContext = namedtuple("TraceContext", ["activation", "span", "token"])
-_HANDLER_CONTEXT_KEY = "_otel_trace_context_key"
-_OTEL_PATCHED_KEY = "_otel_patched_key"
-
-
-def get_excluded_urls():
- urls = configuration.Configuration().TORNADO_EXCLUDED_URLS or ""
- if urls:
- urls = str.split(urls, ",")
- return ExcludeList(urls)
-
-
-def get_traced_request_attrs():
- attrs = configuration.Configuration().TORNADO_TRACED_REQUEST_ATTRS or ""
- if attrs:
- attrs = [attr.strip() for attr in attrs.split(",")]
- else:
- attrs = []
- return attrs
-
-
-_excluded_urls = get_excluded_urls()
-_traced_attrs = get_traced_request_attrs()
-
-carrier_getter = DictGetter()
-
-
-class TornadoInstrumentor(BaseInstrumentor):
- patched_handlers = []
- original_handler_new = None
-
- def _instrument(self, **kwargs):
- """
- _instrument patches tornado.web.RequestHandler and tornado.httpclient.AsyncHTTPClient classes
- to automatically instrument requests both received and sent by Tornado.
-
- We don't patch RequestHandler._execute as it causes some issues with contextvars based context.
- Mainly the context fails to detach from within RequestHandler.on_finish() if it is attached inside
- RequestHandler._execute. Same issue plagues RequestHandler.initialize. RequestHandler.prepare works
- perfectly on the other hand as it executes in the same context as on_finish and log_exection which
- are patched to finish a span after a request is served.
-
- However, we cannot just patch RequestHandler's prepare method because it is supposed to be overwridden
- by sub-classes and since the parent prepare method does not do anything special, sub-classes don't
- have to call super() when overriding the method.
-
- In order to work around this, we patch the __init__ method of RequestHandler and then dynamically patch
- the prepare, on_finish and log_exception methods of the derived classes _only_ the first time we see them.
- Note that the patch does not apply on every single __init__ call, only the first one for the enture
- process lifetime.
- """
- tracer_provider = kwargs.get("tracer_provider")
- tracer = trace.get_tracer(__name__, __version__, tracer_provider)
-
- def handler_init(init, handler, args, kwargs):
- cls = handler.__class__
- if patch_handler_class(tracer, cls):
- self.patched_handlers.append(cls)
- return init(*args, **kwargs)
-
- wrap_function_wrapper(
- "tornado.web", "RequestHandler.__init__", handler_init
- )
- wrap_function_wrapper(
- "tornado.httpclient",
- "AsyncHTTPClient.fetch",
- partial(fetch_async, tracer),
- )
-
- def _uninstrument(self, **kwargs):
- unwrap(tornado.web.RequestHandler, "__init__")
- unwrap(tornado.httpclient.AsyncHTTPClient, "fetch")
- for handler in self.patched_handlers:
- unpatch_handler_class(handler)
- self.patched_handlers = []
-
-
-def patch_handler_class(tracer, cls):
- if getattr(cls, _OTEL_PATCHED_KEY, False):
- return False
-
- setattr(cls, _OTEL_PATCHED_KEY, True)
- _wrap(cls, "prepare", partial(_prepare, tracer))
- _wrap(cls, "on_finish", partial(_on_finish, tracer))
- _wrap(cls, "log_exception", partial(_log_exception, tracer))
- return True
-
-
-def unpatch_handler_class(cls):
- if not getattr(cls, _OTEL_PATCHED_KEY, False):
- return
-
- unwrap(cls, "prepare")
- unwrap(cls, "on_finish")
- unwrap(cls, "log_exception")
- delattr(cls, _OTEL_PATCHED_KEY)
-
-
-def _wrap(cls, method_name, wrapper):
- original = getattr(cls, method_name)
- wrapper = wrapt.FunctionWrapper(original, wrapper)
- wrapt.apply_patch(cls, method_name, wrapper)
-
-
-def _prepare(tracer, func, handler, args, kwargs):
- start_time = time_ns()
- request = handler.request
- if _excluded_urls.url_disabled(request.uri):
- return func(*args, **kwargs)
- _start_span(tracer, handler, start_time)
- return func(*args, **kwargs)
-
-
-def _on_finish(tracer, func, handler, args, kwargs):
- _finish_span(tracer, handler)
- return func(*args, **kwargs)
-
-
-def _log_exception(tracer, func, handler, args, kwargs):
- error = None
- if len(args) == 3:
- error = args[1]
-
- _finish_span(tracer, handler, error)
- return func(*args, **kwargs)
-
-
-def _get_attributes_from_request(request):
- attrs = {
- "component": "tornado",
- "http.method": request.method,
- "http.scheme": request.protocol,
- "http.host": request.host,
- "http.target": request.path,
- }
-
- if request.host:
- attrs["http.host"] = request.host
-
- if request.remote_ip:
- attrs["net.peer.ip"] = request.remote_ip
-
- return extract_attributes_from_object(request, _traced_attrs, attrs)
-
-
-def _get_operation_name(handler, request):
- full_class_name = type(handler).__name__
- class_name = full_class_name.rsplit(".")[-1]
- return "{0}.{1}".format(class_name, request.method.lower())
-
-
-def _start_span(tracer, handler, start_time) -> _TraceContext:
- token = context.attach(
- propagators.extract(carrier_getter, handler.request.headers,)
- )
-
- span = tracer.start_span(
- _get_operation_name(handler, handler.request),
- kind=trace.SpanKind.SERVER,
- start_time=start_time,
- )
- if span.is_recording():
- attributes = _get_attributes_from_request(handler.request)
- for key, value in attributes.items():
- span.set_attribute(key, value)
-
- activation = tracer.use_span(span, end_on_exit=True)
- activation.__enter__()
- ctx = _TraceContext(activation, span, token)
- setattr(handler, _HANDLER_CONTEXT_KEY, ctx)
- return ctx
-
-
-def _finish_span(tracer, handler, error=None):
- status_code = handler.get_status()
- reason = getattr(handler, "_reason")
- finish_args = (None, None, None)
- ctx = getattr(handler, _HANDLER_CONTEXT_KEY, None)
-
- if error:
- if isinstance(error, tornado.web.HTTPError):
- status_code = error.status_code
- if not ctx and status_code == 404:
- ctx = _start_span(tracer, handler, time_ns())
- if status_code != 404:
- finish_args = (
- type(error),
- error,
- getattr(error, "__traceback__", None),
- )
- status_code = 500
- reason = None
-
- if not ctx:
- return
-
- if ctx.span.is_recording():
- if reason:
- ctx.span.set_attribute("http.status_text", reason)
- ctx.span.set_attribute("http.status_code", status_code)
- ctx.span.set_status(
- Status(
- status_code=http_status_to_status_code(status_code),
- description=reason,
- )
- )
-
- ctx.activation.__exit__(*finish_args)
- context.detach(ctx.token)
- delattr(handler, _HANDLER_CONTEXT_KEY)
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/client.py b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/client.py
deleted file mode 100644
index 5ec001bdab4..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/client.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import functools
-
-from tornado.httpclient import HTTPError, HTTPRequest
-
-from opentelemetry import propagators, trace
-from opentelemetry.instrumentation.utils import http_status_to_status_code
-from opentelemetry.trace.status import Status
-from opentelemetry.util import time_ns
-
-
-def _normalize_request(args, kwargs):
- req = args[0]
- if not isinstance(req, str):
- return (args, kwargs)
-
- new_kwargs = {}
- for param in ("callback", "raise_error"):
- if param in kwargs:
- new_kwargs[param] = kwargs.pop(param)
-
- req = HTTPRequest(req, **kwargs)
- new_args = [req]
- new_args.extend(args[1:])
- return (new_args, new_kwargs)
-
-
-def fetch_async(tracer, func, _, args, kwargs):
- start_time = time_ns()
-
- # Return immediately if no args were provided (error)
- # or original_request is set (meaning we are in a redirect step).
- if len(args) == 0 or hasattr(args[0], "original_request"):
- return func(*args, **kwargs)
-
- # Force the creation of a HTTPRequest object if needed,
- # so we can inject the context into the headers.
- args, kwargs = _normalize_request(args, kwargs)
- request = args[0]
-
- span = tracer.start_span(
- request.method, kind=trace.SpanKind.CLIENT, start_time=start_time,
- )
-
- if span.is_recording():
- attributes = {
- "component": "tornado",
- "http.url": request.url,
- "http.method": request.method,
- }
- for key, value in attributes.items():
- span.set_attribute(key, value)
-
- with tracer.use_span(span):
- propagators.inject(type(request.headers).__setitem__, request.headers)
- future = func(*args, **kwargs)
- future.add_done_callback(
- functools.partial(_finish_tracing_callback, span=span)
- )
- return future
-
-
-def _finish_tracing_callback(future, span):
- status_code = None
- description = None
- exc = future.exception()
- if span.is_recording() and exc:
- if isinstance(exc, HTTPError):
- status_code = exc.code
- description = "{}: {}".format(type(exc).__name__, exc)
- else:
- status_code = future.result().code
-
- if status_code is not None:
- span.set_attribute("http.status_code", status_code)
- span.set_status(
- Status(
- status_code=http_status_to_status_code(status_code),
- description=description,
- )
- )
- span.end()
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/version.py b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-tornado/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py b/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py
deleted file mode 100644
index 5b429766ec3..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py
+++ /dev/null
@@ -1,392 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest.mock import Mock, patch
-
-from tornado.testing import AsyncHTTPTestCase
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.tornado import (
- TornadoInstrumentor,
- patch_handler_class,
- unpatch_handler_class,
-)
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace import SpanKind
-from opentelemetry.util import ExcludeList
-
-from .tornado_test_app import (
- AsyncHandler,
- DynamicHandler,
- MainHandler,
- make_app,
-)
-
-
-class TornadoTest(AsyncHTTPTestCase, TestBase):
- def get_app(self):
- tracer = trace.get_tracer(__name__)
- app = make_app(tracer)
- return app
-
- def setUp(self):
- TornadoInstrumentor().instrument()
- super().setUp()
-
- def tearDown(self):
- TornadoInstrumentor().uninstrument()
- super().tearDown()
-
-
-class TestTornadoInstrumentor(TornadoTest):
- def test_patch_references(self):
- self.assertEqual(len(TornadoInstrumentor().patched_handlers), 0)
-
- self.fetch("/")
- self.fetch("/async")
- self.assertEqual(
- TornadoInstrumentor().patched_handlers, [MainHandler, AsyncHandler]
- )
-
- self.fetch("/async")
- self.fetch("/")
- self.assertEqual(
- TornadoInstrumentor().patched_handlers, [MainHandler, AsyncHandler]
- )
-
- TornadoInstrumentor().uninstrument()
- self.assertEqual(TornadoInstrumentor().patched_handlers, [])
-
- def test_patch_applied_only_once(self):
- tracer = trace.get_tracer(__name__)
- self.assertTrue(patch_handler_class(tracer, AsyncHandler))
- self.assertFalse(patch_handler_class(tracer, AsyncHandler))
- self.assertFalse(patch_handler_class(tracer, AsyncHandler))
- unpatch_handler_class(AsyncHandler)
-
-
-class TestTornadoInstrumentation(TornadoTest):
- def test_http_calls(self):
- methods = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]
- for method in methods:
- self._test_http_method_call(method)
-
- def _test_http_method_call(self, method):
- body = "" if method in ["POST", "PUT", "PATCH"] else None
- response = self.fetch("/", method=method, body=body)
- self.assertEqual(response.code, 201)
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 3)
-
- manual, server, client = self.sorted_spans(spans)
-
- self.assertEqual(manual.name, "manual")
- self.assertEqual(manual.parent, server.context)
- self.assertEqual(manual.context.trace_id, client.context.trace_id)
-
- self.assertEqual(server.name, "MainHandler." + method.lower())
- self.assertTrue(server.parent.is_remote)
- self.assertNotEqual(server.parent, client.context)
- self.assertEqual(server.parent.span_id, client.context.span_id)
- self.assertEqual(server.context.trace_id, client.context.trace_id)
- self.assertEqual(server.kind, SpanKind.SERVER)
- self.assert_span_has_attributes(
- server,
- {
- "component": "tornado",
- "http.method": method,
- "http.scheme": "http",
- "http.host": "127.0.0.1:" + str(self.get_http_port()),
- "http.target": "/",
- "net.peer.ip": "127.0.0.1",
- "http.status_text": "Created",
- "http.status_code": 201,
- },
- )
-
- self.assertEqual(client.name, method)
- self.assertFalse(client.context.is_remote)
- self.assertIsNone(client.parent)
- self.assertEqual(client.kind, SpanKind.CLIENT)
- self.assert_span_has_attributes(
- client,
- {
- "component": "tornado",
- "http.url": self.get_url("/"),
- "http.method": method,
- "http.status_code": 201,
- },
- )
-
- self.memory_exporter.clear()
-
- def test_not_recording(self):
- mock_tracer = Mock()
- mock_span = Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = True
- with patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- self.fetch("/")
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_async_handler(self):
- self._test_async_handler("/async", "AsyncHandler")
-
- def test_coroutine_handler(self):
- self._test_async_handler("/cor", "CoroutineHandler")
-
- def _test_async_handler(self, url, handler_name):
- response = self.fetch(url)
- self.assertEqual(response.code, 201)
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 5)
-
- sub2, sub1, sub_wrapper, server, client = self.sorted_spans(spans)
-
- self.assertEqual(sub2.name, "sub-task-2")
- self.assertEqual(sub2.parent, sub_wrapper.context)
- self.assertEqual(sub2.context.trace_id, client.context.trace_id)
-
- self.assertEqual(sub1.name, "sub-task-1")
- self.assertEqual(sub1.parent, sub_wrapper.context)
- self.assertEqual(sub1.context.trace_id, client.context.trace_id)
-
- self.assertEqual(sub_wrapper.name, "sub-task-wrapper")
- self.assertEqual(sub_wrapper.parent, server.context)
- self.assertEqual(sub_wrapper.context.trace_id, client.context.trace_id)
-
- self.assertEqual(server.name, handler_name + ".get")
- self.assertTrue(server.parent.is_remote)
- self.assertNotEqual(server.parent, client.context)
- self.assertEqual(server.parent.span_id, client.context.span_id)
- self.assertEqual(server.context.trace_id, client.context.trace_id)
- self.assertEqual(server.kind, SpanKind.SERVER)
- self.assert_span_has_attributes(
- server,
- {
- "component": "tornado",
- "http.method": "GET",
- "http.scheme": "http",
- "http.host": "127.0.0.1:" + str(self.get_http_port()),
- "http.target": url,
- "net.peer.ip": "127.0.0.1",
- "http.status_text": "Created",
- "http.status_code": 201,
- },
- )
-
- self.assertEqual(client.name, "GET")
- self.assertFalse(client.context.is_remote)
- self.assertIsNone(client.parent)
- self.assertEqual(client.kind, SpanKind.CLIENT)
- self.assert_span_has_attributes(
- client,
- {
- "component": "tornado",
- "http.url": self.get_url(url),
- "http.method": "GET",
- "http.status_code": 201,
- },
- )
-
- def test_500(self):
- response = self.fetch("/error")
- self.assertEqual(response.code, 500)
-
- spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
- self.assertEqual(len(spans), 2)
- server, client = spans
-
- self.assertEqual(server.name, "BadHandler.get")
- self.assertEqual(server.kind, SpanKind.SERVER)
- self.assert_span_has_attributes(
- server,
- {
- "component": "tornado",
- "http.method": "GET",
- "http.scheme": "http",
- "http.host": "127.0.0.1:" + str(self.get_http_port()),
- "http.target": "/error",
- "net.peer.ip": "127.0.0.1",
- "http.status_code": 500,
- },
- )
-
- self.assertEqual(client.name, "GET")
- self.assertEqual(client.kind, SpanKind.CLIENT)
- self.assert_span_has_attributes(
- client,
- {
- "component": "tornado",
- "http.url": self.get_url("/error"),
- "http.method": "GET",
- "http.status_code": 500,
- },
- )
-
- def test_404(self):
- response = self.fetch("/missing-url")
- self.assertEqual(response.code, 404)
-
- spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
- self.assertEqual(len(spans), 2)
- server, client = spans
-
- self.assertEqual(server.name, "ErrorHandler.get")
- self.assertEqual(server.kind, SpanKind.SERVER)
- self.assert_span_has_attributes(
- server,
- {
- "component": "tornado",
- "http.method": "GET",
- "http.scheme": "http",
- "http.host": "127.0.0.1:" + str(self.get_http_port()),
- "http.target": "/missing-url",
- "net.peer.ip": "127.0.0.1",
- "http.status_text": "Not Found",
- "http.status_code": 404,
- },
- )
-
- self.assertEqual(client.name, "GET")
- self.assertEqual(client.kind, SpanKind.CLIENT)
- self.assert_span_has_attributes(
- client,
- {
- "component": "tornado",
- "http.url": self.get_url("/missing-url"),
- "http.method": "GET",
- "http.status_code": 404,
- },
- )
-
- def test_dynamic_handler(self):
- response = self.fetch("/dyna")
- self.assertEqual(response.code, 404)
- self.memory_exporter.clear()
-
- self._app.add_handlers(r".+", [(r"/dyna", DynamicHandler)])
-
- response = self.fetch("/dyna")
- self.assertEqual(response.code, 202)
-
- spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
- self.assertEqual(len(spans), 2)
- server, client = spans
-
- self.assertEqual(server.name, "DynamicHandler.get")
- self.assertTrue(server.parent.is_remote)
- self.assertNotEqual(server.parent, client.context)
- self.assertEqual(server.parent.span_id, client.context.span_id)
- self.assertEqual(server.context.trace_id, client.context.trace_id)
- self.assertEqual(server.kind, SpanKind.SERVER)
- self.assert_span_has_attributes(
- server,
- {
- "component": "tornado",
- "http.method": "GET",
- "http.scheme": "http",
- "http.host": "127.0.0.1:" + str(self.get_http_port()),
- "http.target": "/dyna",
- "net.peer.ip": "127.0.0.1",
- "http.status_text": "Accepted",
- "http.status_code": 202,
- },
- )
-
- self.assertEqual(client.name, "GET")
- self.assertFalse(client.context.is_remote)
- self.assertIsNone(client.parent)
- self.assertEqual(client.kind, SpanKind.CLIENT)
- self.assert_span_has_attributes(
- client,
- {
- "component": "tornado",
- "http.url": self.get_url("/dyna"),
- "http.method": "GET",
- "http.status_code": 202,
- },
- )
-
- @patch(
- "opentelemetry.instrumentation.tornado._excluded_urls",
- ExcludeList(["healthz", "ping"]),
- )
- def test_exclude_lists(self):
- def test_excluded(path):
- self.fetch(path)
- spans = self.sorted_spans(
- self.memory_exporter.get_finished_spans()
- )
- self.assertEqual(len(spans), 1)
- client = spans[0]
- self.assertEqual(client.name, "GET")
- self.assertEqual(client.kind, SpanKind.CLIENT)
- self.assert_span_has_attributes(
- client,
- {
- "component": "tornado",
- "http.url": self.get_url(path),
- "http.method": "GET",
- "http.status_code": 200,
- },
- )
- self.memory_exporter.clear()
-
- test_excluded("/healthz")
- test_excluded("/ping")
-
- @patch(
- "opentelemetry.instrumentation.tornado._traced_attrs",
- ["uri", "full_url", "query"],
- )
- def test_traced_attrs(self):
- self.fetch("/ping?q=abc&b=123")
- spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
- self.assertEqual(len(spans), 2)
- server_span = spans[0]
- self.assertEqual(server_span.kind, SpanKind.SERVER)
- self.assert_span_has_attributes(
- server_span, {"uri": "/ping?q=abc&b=123", "query": "q=abc&b=123"}
- )
- self.memory_exporter.clear()
-
-
-class TestTornadoUninstrument(TornadoTest):
- def test_uninstrument(self):
- response = self.fetch("/")
- self.assertEqual(response.code, 201)
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 3)
- manual, server, client = self.sorted_spans(spans)
- self.assertEqual(manual.name, "manual")
- self.assertEqual(server.name, "MainHandler.get")
- self.assertEqual(client.name, "GET")
- self.memory_exporter.clear()
-
- TornadoInstrumentor().uninstrument()
-
- response = self.fetch("/")
- self.assertEqual(response.code, 201)
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- manual = spans[0]
- self.assertEqual(manual.name, "manual")
diff --git a/instrumentation/opentelemetry-instrumentation-tornado/tests/tornado_test_app.py b/instrumentation/opentelemetry-instrumentation-tornado/tests/tornado_test_app.py
deleted file mode 100644
index 307dc60b76d..00000000000
--- a/instrumentation/opentelemetry-instrumentation-tornado/tests/tornado_test_app.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# pylint: disable=W0223,R0201
-
-import tornado.web
-from tornado import gen
-
-
-class AsyncHandler(tornado.web.RequestHandler):
- async def get(self):
- with self.application.tracer.start_as_current_span("sub-task-wrapper"):
- await self.do_something1()
- await self.do_something2()
- self.set_status(201)
- self.write("{}")
-
- async def do_something1(self):
- with self.application.tracer.start_as_current_span("sub-task-1"):
- tornado.gen.sleep(0.1)
-
- async def do_something2(self):
- with self.application.tracer.start_as_current_span("sub-task-2"):
- tornado.gen.sleep(0.1)
-
-
-class CoroutineHandler(tornado.web.RequestHandler):
- @gen.coroutine
- def get(self):
- with self.application.tracer.start_as_current_span("sub-task-wrapper"):
- yield self.do_something1()
- yield self.do_something2()
- self.set_status(201)
- self.write("{}")
-
- @gen.coroutine
- def do_something1(self):
- with self.application.tracer.start_as_current_span("sub-task-1"):
- tornado.gen.sleep(0.1)
-
- @gen.coroutine
- def do_something2(self):
- with self.application.tracer.start_as_current_span("sub-task-2"):
- tornado.gen.sleep(0.1)
-
-
-class MainHandler(tornado.web.RequestHandler):
- def _handler(self):
- with self.application.tracer.start_as_current_span("manual"):
- self.write("Hello, world")
- self.set_status(201)
-
- def get(self):
- return self._handler()
-
- def post(self):
- return self._handler()
-
- def patch(self):
- return self._handler()
-
- def delete(self):
- return self._handler()
-
- def put(self):
- return self._handler()
-
- def head(self):
- return self._handler()
-
- def options(self):
- return self._handler()
-
-
-class BadHandler(tornado.web.RequestHandler):
- def get(self):
- raise NameError("some random name error")
-
-
-class DynamicHandler(tornado.web.RequestHandler):
- def get(self):
- self.set_status(202)
-
-
-class HealthCheckHandler(tornado.web.RequestHandler):
- def get(self):
- self.set_status(200)
-
-
-def make_app(tracer):
- app = tornado.web.Application(
- [
- (r"/", MainHandler),
- (r"/error", BadHandler),
- (r"/cor", CoroutineHandler),
- (r"/async", AsyncHandler),
- (r"/healthz", HealthCheckHandler),
- (r"/ping", HealthCheckHandler),
- ]
- )
- app.tracer = tracer
- return app
diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-wsgi/CHANGELOG.md
deleted file mode 100644
index 68bd25237c8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-wsgi/CHANGELOG.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Changelog
-
-## Unreleased
-
-## Version 0.13b0
-
-Released 2020-09-17
-
-- Drop support for Python 3.4
- ([#1099](https://github.com/open-telemetry/opentelemetry-python/pull/1099))
-
-## Version 0.12b0
-
-Released 2020-08-14
-
-- Change package name to opentelemetry-instrumentation-wsgi
- ([#961](https://github.com/open-telemetry/opentelemetry-python/pull/961))
-
-## Version 0.11b0
-
-Released 2020-07-28
-
-- Set span status on wsgi errors
- ([#864](https://github.com/open-telemetry/opentelemetry-python/pull/864))
-
-## 0.4a0
-
-Released 2020-02-21
-
-- Updating network connection attribute names
- ([#350](https://github.com/open-telemetry/opentelemetry-python/pull/350))
-
-## 0.3a0
-
-Released 2019-12-11
-
-- Support new semantic conventions
- ([#299](https://github.com/open-telemetry/opentelemetry-python/pull/299))
-- Updates for core library changes
-
-## 0.2a0
-
-Released 2019-10-29
-
-- Updates for core library changes
-
-## 0.1a0
-
-Released 2019-09-30
-
-- Initial release
diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/LICENSE b/instrumentation/opentelemetry-instrumentation-wsgi/LICENSE
deleted file mode 100644
index 261eeb9e9f8..00000000000
--- a/instrumentation/opentelemetry-instrumentation-wsgi/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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/instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in
deleted file mode 100644
index aed3e33273b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-graft src
-graft tests
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude __pycache__/*
-include CHANGELOG.md
-include MANIFEST.in
-include README.rst
-include LICENSE
diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/README.rst b/instrumentation/opentelemetry-instrumentation-wsgi/README.rst
deleted file mode 100644
index ac39dac0c7c..00000000000
--- a/instrumentation/opentelemetry-instrumentation-wsgi/README.rst
+++ /dev/null
@@ -1,26 +0,0 @@
-OpenTelemetry WSGI Middleware
-=============================
-
-|pypi|
-
-.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-wsgi.svg
- :target: https://pypi.org/project/opentelemetry-instrumentation-wsgi/
-
-
-This library provides a WSGI middleware that can be used on any WSGI framework
-(such as Django / Flask) to track requests timing through OpenTelemetry.
-
-Installation
-------------
-
-::
-
- pip install opentelemetry-instrumentation-wsgi
-
-
-References
-----------
-
-* `OpenTelemetry WSGI Middleware `_
-* `OpenTelemetry Project `_
-* `WSGI `_
diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg b/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg
deleted file mode 100644
index 585a513412b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright The OpenTelemetry 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.
-#
-[metadata]
-name = opentelemetry-instrumentation-wsgi
-description = WSGI Middleware for OpenTelemetry
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-author = OpenTelemetry Authors
-author_email = cncf-opentelemetry-contributors@lists.cncf.io
-url = https://github.com/open-telemetry/opentelemetry-python/tree/master/instrumentation/opentelemetry-instrumentation-wsgi
-platforms = any
-license = Apache-2.0
-classifiers =
- Development Status :: 4 - Beta
- Intended Audience :: Developers
- License :: OSI Approved :: Apache Software License
- Programming Language :: Python
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
-
-[options]
-python_requires = >=3.5
-package_dir=
- =src
-packages=find_namespace:
-install_requires =
- opentelemetry-api == 0.16.dev0
- opentelemetry-instrumentation == 0.16.dev0
-
-[options.extras_require]
-test =
- opentelemetry-test == 0.16.dev0
-
-[options.packages.find]
-where = src
diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/setup.py b/instrumentation/opentelemetry-instrumentation-wsgi/setup.py
deleted file mode 100644
index fb4ffa7437b..00000000000
--- a/instrumentation/opentelemetry-instrumentation-wsgi/setup.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import setuptools
-
-BASE_DIR = os.path.dirname(__file__)
-VERSION_FILENAME = os.path.join(
- BASE_DIR, "src", "opentelemetry", "instrumentation", "wsgi", "version.py"
-)
-PACKAGE_INFO = {}
-with open(VERSION_FILENAME) as f:
- exec(f.read(), PACKAGE_INFO)
-
-setuptools.setup(version=PACKAGE_INFO["__version__"])
diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py
deleted file mode 100644
index e1ef92c6baf..00000000000
--- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py
+++ /dev/null
@@ -1,248 +0,0 @@
-# Copyright The OpenTelemetry 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.
-"""
-This library provides a WSGI middleware that can be used on any WSGI framework
-(such as Django / Flask) to track requests timing through OpenTelemetry.
-
-Usage (Flask)
--------------
-
-.. code-block:: python
-
- from flask import Flask
- from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware
-
- app = Flask(__name__)
- app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app)
-
- @app.route("/")
- def hello():
- return "Hello!"
-
- if __name__ == "__main__":
- app.run(debug=True)
-
-
-Usage (Django)
---------------
-
-Modify the application's ``wsgi.py`` file as shown below.
-
-.. code-block:: python
-
- import os
- from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware
- from django.core.wsgi import get_wsgi_application
-
- os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
-
- application = get_wsgi_application()
- application = OpenTelemetryMiddleware(application)
-
-API
----
-"""
-
-import functools
-import typing
-import wsgiref.util as wsgiref_util
-
-from opentelemetry import context, propagators, trace
-from opentelemetry.instrumentation.utils import http_status_to_status_code
-from opentelemetry.instrumentation.wsgi.version import __version__
-from opentelemetry.trace.propagation.textmap import DictGetter
-from opentelemetry.trace.status import Status, StatusCode
-
-_HTTP_VERSION_PREFIX = "HTTP/"
-
-
-class CarrierGetter(DictGetter):
- def get(self, carrier: dict, key: str) -> typing.List[str]:
- """Getter implementation to retrieve a HTTP header value from the
- PEP3333-conforming WSGI environ
-
- Args:
- carrier: WSGI environ object
- key: header name in environ object
- Returns:
- A list with a single string with the header value if it exists,
- else an empty list.
- """
- environ_key = "HTTP_" + key.upper().replace("-", "_")
- value = carrier.get(environ_key)
- if value is not None:
- return [value]
- return []
-
- def keys(self, carrier):
- return []
-
-
-carrier_getter = CarrierGetter()
-
-
-def setifnotnone(dic, key, value):
- if value is not None:
- dic[key] = value
-
-
-def collect_request_attributes(environ):
- """Collects HTTP request attributes from the PEP3333-conforming
- WSGI environ and returns a dictionary to be used as span creation attributes."""
-
- result = {
- "component": "http",
- "http.method": environ.get("REQUEST_METHOD"),
- "http.server_name": environ.get("SERVER_NAME"),
- "http.scheme": environ.get("wsgi.url_scheme"),
- }
-
- host_port = environ.get("SERVER_PORT")
- if host_port is not None:
- result.update({"host.port": int(host_port)})
-
- setifnotnone(result, "http.host", environ.get("HTTP_HOST"))
- target = environ.get("RAW_URI")
- if target is None: # Note: `"" or None is None`
- target = environ.get("REQUEST_URI")
- if target is not None:
- result["http.target"] = target
- else:
- result["http.url"] = wsgiref_util.request_uri(environ)
-
- remote_addr = environ.get("REMOTE_ADDR")
- if remote_addr:
- result["net.peer.ip"] = remote_addr
- remote_host = environ.get("REMOTE_HOST")
- if remote_host and remote_host != remote_addr:
- result["net.peer.name"] = remote_host
-
- user_agent = environ.get("HTTP_USER_AGENT")
- if user_agent is not None and len(user_agent) > 0:
- result["http.user_agent"] = user_agent
-
- setifnotnone(result, "net.peer.port", environ.get("REMOTE_PORT"))
- flavor = environ.get("SERVER_PROTOCOL", "")
- if flavor.upper().startswith(_HTTP_VERSION_PREFIX):
- flavor = flavor[len(_HTTP_VERSION_PREFIX) :]
- if flavor:
- result["http.flavor"] = flavor
-
- return result
-
-
-def add_response_attributes(
- span, start_response_status, response_headers
-): # pylint: disable=unused-argument
- """Adds HTTP response attributes to span using the arguments
- passed to a PEP3333-conforming start_response callable."""
- if not span.is_recording():
- return
- status_code, status_text = start_response_status.split(" ", 1)
- span.set_attribute("http.status_text", status_text)
-
- try:
- status_code = int(status_code)
- except ValueError:
- span.set_status(
- Status(
- StatusCode.ERROR,
- "Non-integer HTTP status: " + repr(status_code),
- )
- )
- else:
- span.set_attribute("http.status_code", status_code)
- span.set_status(Status(http_status_to_status_code(status_code)))
-
-
-def get_default_span_name(environ):
- """Default implementation for name_callback, returns HTTP {METHOD_NAME}."""
- return "HTTP {}".format(environ.get("REQUEST_METHOD", "")).strip()
-
-
-class OpenTelemetryMiddleware:
- """The WSGI application middleware.
-
- This class is a PEP 3333 conforming WSGI middleware that starts and
- annotates spans for any requests it is invoked with.
-
- Args:
- wsgi: The WSGI application callable to forward requests to.
- name_callback: Callback which calculates a generic span name for an
- incoming HTTP request based on the PEP3333 WSGI environ.
- Optional: Defaults to get_default_span_name.
- """
-
- def __init__(self, wsgi, name_callback=get_default_span_name):
- self.wsgi = wsgi
- self.tracer = trace.get_tracer(__name__, __version__)
- self.name_callback = name_callback
-
- @staticmethod
- def _create_start_response(span, start_response):
- @functools.wraps(start_response)
- def _start_response(status, response_headers, *args, **kwargs):
- add_response_attributes(span, status, response_headers)
- return start_response(status, response_headers, *args, **kwargs)
-
- return _start_response
-
- def __call__(self, environ, start_response):
- """The WSGI application
-
- Args:
- environ: A WSGI environment.
- start_response: The WSGI start_response callable.
- """
-
- token = context.attach(propagators.extract(carrier_getter, environ))
- span_name = self.name_callback(environ)
-
- span = self.tracer.start_span(
- span_name,
- kind=trace.SpanKind.SERVER,
- attributes=collect_request_attributes(environ),
- )
-
- try:
- with self.tracer.use_span(span):
- start_response = self._create_start_response(
- span, start_response
- )
- iterable = self.wsgi(environ, start_response)
- return _end_span_after_iterating(
- iterable, span, self.tracer, token
- )
- except Exception as ex:
- if span.is_recording():
- span.set_status(Status(StatusCode.ERROR, str(ex)))
- span.end()
- context.detach(token)
- raise
-
-
-# Put this in a subfunction to not delay the call to the wrapped
-# WSGI application (instrumentation should change the application
-# behavior as little as possible).
-def _end_span_after_iterating(iterable, span, tracer, token):
- try:
- with tracer.use_span(span):
- for yielded in iterable:
- yield yielded
- finally:
- close = getattr(iterable, "close", None)
- if close:
- close()
- span.end()
- context.detach(token)
diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/version.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/version.py
deleted file mode 100644
index 1f98d44fa88..00000000000
--- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright The OpenTelemetry 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.
-
-__version__ = "0.16.dev0"
diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py b/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py
deleted file mode 100644
index 144b4cf0692..00000000000
--- a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py
+++ /dev/null
@@ -1,359 +0,0 @@
-# Copyright The OpenTelemetry 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 sys
-import unittest
-import unittest.mock as mock
-import wsgiref.util as wsgiref_util
-from urllib.parse import urlsplit
-
-import opentelemetry.instrumentation.wsgi as otel_wsgi
-from opentelemetry import trace as trace_api
-from opentelemetry.test.wsgitestutil import WsgiTestBase
-from opentelemetry.trace.status import StatusCode
-
-
-class Response:
- def __init__(self):
- self.iter = iter([b"*"])
- self.close_calls = 0
-
- def __iter__(self):
- return self
-
- def __next__(self):
- return next(self.iter)
-
- def close(self):
- self.close_calls += 1
-
-
-def simple_wsgi(environ, start_response):
- assert isinstance(environ, dict)
- start_response("200 OK", [("Content-Type", "text/plain")])
- return [b"*"]
-
-
-def create_iter_wsgi(response):
- def iter_wsgi(environ, start_response):
- assert isinstance(environ, dict)
- start_response("200 OK", [("Content-Type", "text/plain")])
- return response
-
- return iter_wsgi
-
-
-def create_gen_wsgi(response):
- def gen_wsgi(environ, start_response):
- result = create_iter_wsgi(response)(environ, start_response)
- yield from result
- getattr(result, "close", lambda: None)()
-
- return gen_wsgi
-
-
-def error_wsgi(environ, start_response):
- assert isinstance(environ, dict)
- try:
- raise ValueError
- except ValueError:
- exc_info = sys.exc_info()
- start_response("200 OK", [("Content-Type", "text/plain")], exc_info)
- exc_info = None
- return [b"*"]
-
-
-def error_wsgi_unhandled(environ, start_response):
- assert isinstance(environ, dict)
- raise ValueError
-
-
-class TestWsgiApplication(WsgiTestBase):
- def validate_response(
- self, response, error=None, span_name="HTTP GET", http_method="GET"
- ):
- while True:
- try:
- value = next(response)
- self.assertEqual(value, b"*")
- except StopIteration:
- break
-
- self.assertEqual(self.status, "200 OK")
- self.assertEqual(
- self.response_headers, [("Content-Type", "text/plain")]
- )
- if error:
- self.assertIs(self.exc_info[0], error)
- self.assertIsInstance(self.exc_info[1], error)
- self.assertIsNotNone(self.exc_info[2])
- else:
- self.assertIsNone(self.exc_info)
-
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
- self.assertEqual(span_list[0].name, span_name)
- self.assertEqual(span_list[0].kind, trace_api.SpanKind.SERVER)
- expected_attributes = {
- "component": "http",
- "http.server_name": "127.0.0.1",
- "http.scheme": "http",
- "host.port": 80,
- "http.host": "127.0.0.1",
- "http.flavor": "1.0",
- "http.url": "http://127.0.0.1/",
- "http.status_text": "OK",
- "http.status_code": 200,
- }
- if http_method is not None:
- expected_attributes["http.method"] = http_method
- self.assertEqual(span_list[0].attributes, expected_attributes)
-
- def test_basic_wsgi_call(self):
- app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi)
- response = app(self.environ, self.start_response)
- self.validate_response(response)
-
- def test_wsgi_not_recording(self):
- mock_tracer = mock.Mock()
- mock_span = mock.Mock()
- mock_span.is_recording.return_value = False
- mock_tracer.start_span.return_value = mock_span
- mock_tracer.use_span.return_value.__enter__ = mock_span
- mock_tracer.use_span.return_value.__exit__ = mock_span
- with mock.patch("opentelemetry.trace.get_tracer") as tracer:
- tracer.return_value = mock_tracer
- app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi)
- # pylint: disable=W0612
- response = app(self.environ, self.start_response) # noqa: F841
- self.assertFalse(mock_span.is_recording())
- self.assertTrue(mock_span.is_recording.called)
- self.assertFalse(mock_span.set_attribute.called)
- self.assertFalse(mock_span.set_status.called)
-
- def test_wsgi_iterable(self):
- original_response = Response()
- iter_wsgi = create_iter_wsgi(original_response)
- app = otel_wsgi.OpenTelemetryMiddleware(iter_wsgi)
- response = app(self.environ, self.start_response)
- # Verify that start_response has been called
- self.assertTrue(self.status)
- self.validate_response(response)
-
- # Verify that close has been called exactly once
- self.assertEqual(1, original_response.close_calls)
-
- def test_wsgi_generator(self):
- original_response = Response()
- gen_wsgi = create_gen_wsgi(original_response)
- app = otel_wsgi.OpenTelemetryMiddleware(gen_wsgi)
- response = app(self.environ, self.start_response)
- # Verify that start_response has not been called
- self.assertIsNone(self.status)
- self.validate_response(response)
-
- # Verify that close has been called exactly once
- self.assertEqual(original_response.close_calls, 1)
-
- def test_wsgi_exc_info(self):
- app = otel_wsgi.OpenTelemetryMiddleware(error_wsgi)
- response = app(self.environ, self.start_response)
- self.validate_response(response, error=ValueError)
-
- def test_wsgi_internal_error(self):
- app = otel_wsgi.OpenTelemetryMiddleware(error_wsgi_unhandled)
- self.assertRaises(ValueError, app, self.environ, self.start_response)
- span_list = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(span_list), 1)
- self.assertEqual(
- span_list[0].status.status_code, StatusCode.ERROR,
- )
-
- def test_override_span_name(self):
- """Test that span_names can be overwritten by our callback function."""
- span_name = "Dymaxion"
-
- def get_predefined_span_name(scope):
- # pylint: disable=unused-argument
- return span_name
-
- app = otel_wsgi.OpenTelemetryMiddleware(
- simple_wsgi, name_callback=get_predefined_span_name
- )
- response = app(self.environ, self.start_response)
- self.validate_response(response, span_name=span_name)
-
- def test_default_span_name_missing_request_method(self):
- """Test that default span_names with missing request method."""
- self.environ.pop("REQUEST_METHOD")
- app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi)
- response = app(self.environ, self.start_response)
- self.validate_response(response, span_name="HTTP", http_method=None)
-
-
-class TestWsgiAttributes(unittest.TestCase):
- def setUp(self):
- self.environ = {}
- wsgiref_util.setup_testing_defaults(self.environ)
- self.span = mock.create_autospec(trace_api.Span, spec_set=True)
-
- def test_request_attributes(self):
- self.environ["QUERY_STRING"] = "foo=bar"
-
- attrs = otel_wsgi.collect_request_attributes(self.environ)
- self.assertDictEqual(
- attrs,
- {
- "component": "http",
- "http.method": "GET",
- "http.host": "127.0.0.1",
- "http.url": "http://127.0.0.1/?foo=bar",
- "host.port": 80,
- "http.scheme": "http",
- "http.server_name": "127.0.0.1",
- "http.flavor": "1.0",
- },
- )
-
- def validate_url(self, expected_url, raw=False, has_host=True):
- parts = urlsplit(expected_url)
- expected = {
- "http.scheme": parts.scheme,
- "host.port": parts.port or (80 if parts.scheme == "http" else 443),
- "http.server_name": parts.hostname, # Not true in the general case, but for all tests.
- }
- if raw:
- expected["http.target"] = expected_url.split(parts.netloc, 1)[1]
- else:
- expected["http.url"] = expected_url
- if has_host:
- expected["http.host"] = parts.hostname
-
- attrs = otel_wsgi.collect_request_attributes(self.environ)
- self.assertGreaterEqual(
- attrs.items(), expected.items(), expected_url + " expected."
- )
-
- def test_request_attributes_with_partial_raw_uri(self):
- self.environ["RAW_URI"] = "/#top"
- self.validate_url("http://127.0.0.1/#top", raw=True)
-
- def test_request_attributes_with_partial_raw_uri_and_nonstandard_port(
- self,
- ):
- self.environ["RAW_URI"] = "/?"
- del self.environ["HTTP_HOST"]
- self.environ["SERVER_PORT"] = "8080"
- self.validate_url("http://127.0.0.1:8080/?", raw=True, has_host=False)
-
- def test_https_uri_port(self):
- del self.environ["HTTP_HOST"]
- self.environ["SERVER_PORT"] = "443"
- self.environ["wsgi.url_scheme"] = "https"
- self.validate_url("https://127.0.0.1/", has_host=False)
-
- self.environ["SERVER_PORT"] = "8080"
- self.validate_url("https://127.0.0.1:8080/", has_host=False)
-
- self.environ["SERVER_PORT"] = "80"
- self.validate_url("https://127.0.0.1:80/", has_host=False)
-
- def test_http_uri_port(self):
- del self.environ["HTTP_HOST"]
- self.environ["SERVER_PORT"] = "80"
- self.environ["wsgi.url_scheme"] = "http"
- self.validate_url("http://127.0.0.1/", has_host=False)
-
- self.environ["SERVER_PORT"] = "8080"
- self.validate_url("http://127.0.0.1:8080/", has_host=False)
-
- self.environ["SERVER_PORT"] = "443"
- self.validate_url("http://127.0.0.1:443/", has_host=False)
-
- def test_request_attributes_with_nonstandard_port_and_no_host(self):
- del self.environ["HTTP_HOST"]
- self.environ["SERVER_PORT"] = "8080"
- self.validate_url("http://127.0.0.1:8080/", has_host=False)
-
- self.environ["SERVER_PORT"] = "443"
- self.validate_url("http://127.0.0.1:443/", has_host=False)
-
- def test_request_attributes_with_conflicting_nonstandard_port(self):
- self.environ[
- "HTTP_HOST"
- ] += ":8080" # Note that we do not correct SERVER_PORT
- expected = {
- "http.host": "127.0.0.1:8080",
- "http.url": "http://127.0.0.1:8080/",
- "host.port": 80,
- }
- self.assertGreaterEqual(
- otel_wsgi.collect_request_attributes(self.environ).items(),
- expected.items(),
- )
-
- def test_request_attributes_with_faux_scheme_relative_raw_uri(self):
- self.environ["RAW_URI"] = "//127.0.0.1/?"
- self.validate_url("http://127.0.0.1//127.0.0.1/?", raw=True)
-
- def test_request_attributes_pathless(self):
- self.environ["RAW_URI"] = ""
- expected = {"http.target": ""}
- self.assertGreaterEqual(
- otel_wsgi.collect_request_attributes(self.environ).items(),
- expected.items(),
- )
-
- def test_request_attributes_with_full_request_uri(self):
- self.environ["HTTP_HOST"] = "127.0.0.1:8080"
- self.environ["REQUEST_METHOD"] = "CONNECT"
- self.environ[
- "REQUEST_URI"
- ] = "127.0.0.1:8080" # Might happen in a CONNECT request
- expected = {
- "http.host": "127.0.0.1:8080",
- "http.target": "127.0.0.1:8080",
- }
- self.assertGreaterEqual(
- otel_wsgi.collect_request_attributes(self.environ).items(),
- expected.items(),
- )
-
- def test_http_user_agent_attribute(self):
- self.environ["HTTP_USER_AGENT"] = "test-useragent"
- expected = {"http.user_agent": "test-useragent"}
- self.assertGreaterEqual(
- otel_wsgi.collect_request_attributes(self.environ).items(),
- expected.items(),
- )
-
- def test_response_attributes(self):
- otel_wsgi.add_response_attributes(self.span, "404 Not Found", {})
- expected = (
- mock.call("http.status_code", 404),
- mock.call("http.status_text", "Not Found"),
- )
- self.assertEqual(self.span.set_attribute.call_count, len(expected))
- self.span.set_attribute.assert_has_calls(expected, any_order=True)
-
- def test_response_attributes_invalid_status_code(self):
- otel_wsgi.add_response_attributes(self.span, "Invalid Status Code", {})
- self.assertEqual(self.span.set_attribute.call_count, 1)
- self.span.set_attribute.assert_called_with(
- "http.status_text", "Status Code"
- )
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/tests/opentelemetry-docker-tests/tests/asyncpg/test_asyncpg_functional.py b/tests/opentelemetry-docker-tests/tests/asyncpg/test_asyncpg_functional.py
deleted file mode 100644
index 2e37efe2246..00000000000
--- a/tests/opentelemetry-docker-tests/tests/asyncpg/test_asyncpg_functional.py
+++ /dev/null
@@ -1,260 +0,0 @@
-import asyncio
-import os
-
-import asyncpg
-
-from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor
-from opentelemetry.test.test_base import TestBase
-from opentelemetry.trace.status import StatusCode
-
-POSTGRES_HOST = os.getenv("POSTGRESQL_HOST ", "localhost")
-POSTGRES_PORT = int(os.getenv("POSTGRESQL_PORT ", "5432"))
-POSTGRES_DB_NAME = os.getenv("POSTGRESQL_DB_NAME ", "opentelemetry-tests")
-POSTGRES_PASSWORD = os.getenv("POSTGRESQL_HOST ", "testpassword")
-POSTGRES_USER = os.getenv("POSTGRESQL_HOST ", "testuser")
-
-
-def async_call(coro):
- loop = asyncio.get_event_loop()
- return loop.run_until_complete(coro)
-
-
-class TestFunctionalAsyncPG(TestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls._connection = None
- cls._cursor = None
- cls._tracer = cls.tracer_provider.get_tracer(__name__)
- AsyncPGInstrumentor().instrument(tracer_provider=cls.tracer_provider)
- cls._connection = async_call(
- asyncpg.connect(
- database=POSTGRES_DB_NAME,
- user=POSTGRES_USER,
- password=POSTGRES_PASSWORD,
- host=POSTGRES_HOST,
- port=POSTGRES_PORT,
- )
- )
-
- @classmethod
- def tearDownClass(cls):
- AsyncPGInstrumentor().uninstrument()
-
- def test_instrumented_execute_method_without_arguments(self, *_, **__):
- async_call(self._connection.execute("SELECT 42;"))
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
- self.assertEqual(
- spans[0].attributes,
- {
- "db.type": "sql",
- "db.user": POSTGRES_USER,
- "db.instance": POSTGRES_DB_NAME,
- "db.statement": "SELECT 42;",
- },
- )
-
- def test_instrumented_fetch_method_without_arguments(self, *_, **__):
- async_call(self._connection.fetch("SELECT 42;"))
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- self.assertEqual(
- spans[0].attributes,
- {
- "db.type": "sql",
- "db.user": POSTGRES_USER,
- "db.instance": POSTGRES_DB_NAME,
- "db.statement": "SELECT 42;",
- },
- )
-
- def test_instrumented_transaction_method(self, *_, **__):
- async def _transaction_execute():
- async with self._connection.transaction():
- await self._connection.execute("SELECT 42;")
-
- async_call(_transaction_execute())
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(3, len(spans))
- self.assertEqual(
- {
- "db.instance": POSTGRES_DB_NAME,
- "db.user": POSTGRES_USER,
- "db.type": "sql",
- "db.statement": "BEGIN;",
- },
- spans[0].attributes,
- )
- self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
- self.assertEqual(
- {
- "db.instance": POSTGRES_DB_NAME,
- "db.user": POSTGRES_USER,
- "db.type": "sql",
- "db.statement": "SELECT 42;",
- },
- spans[1].attributes,
- )
- self.assertIs(StatusCode.UNSET, spans[1].status.status_code)
- self.assertEqual(
- {
- "db.instance": POSTGRES_DB_NAME,
- "db.user": POSTGRES_USER,
- "db.type": "sql",
- "db.statement": "COMMIT;",
- },
- spans[2].attributes,
- )
- self.assertIs(StatusCode.UNSET, spans[2].status.status_code)
-
- def test_instrumented_failed_transaction_method(self, *_, **__):
- async def _transaction_execute():
- async with self._connection.transaction():
- await self._connection.execute("SELECT 42::uuid;")
-
- with self.assertRaises(asyncpg.CannotCoerceError):
- async_call(_transaction_execute())
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(3, len(spans))
- self.assertEqual(
- {
- "db.instance": POSTGRES_DB_NAME,
- "db.user": POSTGRES_USER,
- "db.type": "sql",
- "db.statement": "BEGIN;",
- },
- spans[0].attributes,
- )
- self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
- self.assertEqual(
- {
- "db.instance": POSTGRES_DB_NAME,
- "db.user": POSTGRES_USER,
- "db.type": "sql",
- "db.statement": "SELECT 42::uuid;",
- },
- spans[1].attributes,
- )
- self.assertEqual(
- StatusCode.ERROR, spans[1].status.status_code,
- )
- self.assertEqual(
- {
- "db.instance": POSTGRES_DB_NAME,
- "db.user": POSTGRES_USER,
- "db.type": "sql",
- "db.statement": "ROLLBACK;",
- },
- spans[2].attributes,
- )
- self.assertIs(StatusCode.UNSET, spans[2].status.status_code)
-
- def test_instrumented_method_doesnt_capture_parameters(self, *_, **__):
- async_call(self._connection.execute("SELECT $1;", "1"))
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
- self.assertEqual(
- spans[0].attributes,
- {
- "db.type": "sql",
- "db.user": POSTGRES_USER,
- # This shouldn't be set because we don't capture parameters by
- # default
- #
- # "db.statement.parameters": "('1',)",
- "db.instance": POSTGRES_DB_NAME,
- "db.statement": "SELECT $1;",
- },
- )
-
-
-class TestFunctionalAsyncPG_CaptureParameters(TestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls._connection = None
- cls._cursor = None
- cls._tracer = cls.tracer_provider.get_tracer(__name__)
- AsyncPGInstrumentor(capture_parameters=True).instrument(
- tracer_provider=cls.tracer_provider
- )
- cls._connection = async_call(
- asyncpg.connect(
- database=POSTGRES_DB_NAME,
- user=POSTGRES_USER,
- password=POSTGRES_PASSWORD,
- host=POSTGRES_HOST,
- port=POSTGRES_PORT,
- )
- )
-
- @classmethod
- def tearDownClass(cls):
- AsyncPGInstrumentor().uninstrument()
-
- def test_instrumented_execute_method_with_arguments(self, *_, **__):
- async_call(self._connection.execute("SELECT $1;", "1"))
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
- self.assertEqual(
- spans[0].attributes,
- {
- "db.type": "sql",
- "db.user": POSTGRES_USER,
- "db.statement.parameters": "('1',)",
- "db.instance": POSTGRES_DB_NAME,
- "db.statement": "SELECT $1;",
- },
- )
-
- def test_instrumented_fetch_method_with_arguments(self, *_, **__):
- async_call(self._connection.fetch("SELECT $1;", "1"))
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- self.assertEqual(
- spans[0].attributes,
- {
- "db.type": "sql",
- "db.user": POSTGRES_USER,
- "db.statement.parameters": "('1',)",
- "db.instance": POSTGRES_DB_NAME,
- "db.statement": "SELECT $1;",
- },
- )
-
- def test_instrumented_executemany_method_with_arguments(self, *_, **__):
- async_call(self._connection.executemany("SELECT $1;", [["1"], ["2"]]))
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- self.assertEqual(
- {
- "db.type": "sql",
- "db.statement": "SELECT $1;",
- "db.statement.parameters": "([['1'], ['2']],)",
- "db.user": POSTGRES_USER,
- "db.instance": POSTGRES_DB_NAME,
- },
- spans[0].attributes,
- )
-
- def test_instrumented_execute_interface_error_method(self, *_, **__):
- with self.assertRaises(asyncpg.InterfaceError):
- async_call(self._connection.execute("SELECT 42;", 1, 2, 3))
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- self.assertEqual(
- spans[0].attributes,
- {
- "db.type": "sql",
- "db.instance": POSTGRES_DB_NAME,
- "db.user": POSTGRES_USER,
- "db.statement.parameters": "(1, 2, 3)",
- "db.statement": "SELECT 42;",
- },
- )
diff --git a/tests/opentelemetry-docker-tests/tests/celery/conftest.py b/tests/opentelemetry-docker-tests/tests/celery/conftest.py
deleted file mode 100644
index 085fe3bab1e..00000000000
--- a/tests/opentelemetry-docker-tests/tests/celery/conftest.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-from functools import wraps
-
-import pytest
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.celery import CeleryInstrumentor
-from opentelemetry.sdk.trace import TracerProvider, export
-from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
- InMemorySpanExporter,
-)
-
-REDIS_HOST = os.getenv("REDIS_HOST", "localhost")
-REDIS_PORT = int(os.getenv("REDIS_PORT ", "6379"))
-REDIS_URL = "redis://{host}:{port}".format(host=REDIS_HOST, port=REDIS_PORT)
-BROKER_URL = "{redis}/{db}".format(redis=REDIS_URL, db=0)
-BACKEND_URL = "{redis}/{db}".format(redis=REDIS_URL, db=1)
-
-
-@pytest.fixture(scope="session")
-def celery_config():
- return {"broker_url": BROKER_URL, "result_backend": BACKEND_URL}
-
-
-@pytest.fixture
-def celery_worker_parameters():
- return {
- # See https://github.com/celery/celery/issues/3642#issuecomment-457773294
- "perform_ping_check": False,
- }
-
-
-@pytest.fixture(autouse=True)
-def patch_celery_app(celery_app, celery_worker):
- """Patch task decorator on app fixture to reload worker"""
- # See https://github.com/celery/celery/issues/3642
- def wrap_task(fn):
- @wraps(fn)
- def wrapper(*args, **kwargs):
- result = fn(*args, **kwargs)
- celery_worker.reload()
- return result
-
- return wrapper
-
- celery_app.task = wrap_task(celery_app.task)
-
-
-@pytest.fixture(autouse=True)
-def instrument(tracer_provider, memory_exporter):
- CeleryInstrumentor().instrument(tracer_provider=tracer_provider)
- memory_exporter.clear()
-
- yield
-
- CeleryInstrumentor().uninstrument()
-
-
-@pytest.fixture(scope="session")
-def tracer_provider(memory_exporter):
- original_tracer_provider = trace_api.get_tracer_provider()
-
- tracer_provider = TracerProvider()
-
- span_processor = export.SimpleExportSpanProcessor(memory_exporter)
- tracer_provider.add_span_processor(span_processor)
-
- trace_api.set_tracer_provider(tracer_provider)
-
- yield tracer_provider
-
- trace_api.set_tracer_provider(original_tracer_provider)
-
-
-@pytest.fixture(scope="session")
-def memory_exporter():
- memory_exporter = InMemorySpanExporter()
- return memory_exporter
diff --git a/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py b/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py
deleted file mode 100644
index 7786890a5fe..00000000000
--- a/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py
+++ /dev/null
@@ -1,537 +0,0 @@
-# Copyright The OpenTelemetry 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 celery
-import pytest
-from celery.exceptions import Retry
-
-import opentelemetry.instrumentation.celery
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.celery import CeleryInstrumentor
-from opentelemetry.sdk import resources
-from opentelemetry.sdk.trace import TracerProvider, export
-from opentelemetry.trace.status import StatusCode
-
-# set a high timeout for async executions due to issues in CI
-ASYNC_GET_TIMEOUT = 120
-
-
-class MyException(Exception):
- pass
-
-
-@pytest.mark.skip(reason="inconsistent test results")
-def test_instrumentation_info(celery_app, memory_exporter):
- @celery_app.task
- def fn_task():
- return 42
-
- result = fn_task.apply_async()
- assert result.get(timeout=ASYNC_GET_TIMEOUT) == 42
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 2
-
- async_span, run_span = spans
-
- assert run_span.parent == async_span.context
- assert run_span.parent.span_id == async_span.context.span_id
- assert run_span.context.trace_id == async_span.context.trace_id
-
- assert async_span.instrumentation_info.name == "apply_async/{0}".format(
- opentelemetry.instrumentation.celery.__name__
- )
- assert async_span.instrumentation_info.version == "apply_async/{0}".format(
- opentelemetry.instrumentation.celery.__version__
- )
- assert run_span.instrumentation_info.name == "run/{0}".format(
- opentelemetry.instrumentation.celery.__name__
- )
- assert run_span.instrumentation_info.version == "run/{0}".format(
- opentelemetry.instrumentation.celery.__version__
- )
-
-
-def test_fn_task_run(celery_app, memory_exporter):
- @celery_app.task
- def fn_task():
- return 42
-
- t = fn_task.run()
- assert t == 42
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 0
-
-
-def test_fn_task_call(celery_app, memory_exporter):
- @celery_app.task
- def fn_task():
- return 42
-
- t = fn_task()
- assert t == 42
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 0
-
-
-def test_fn_task_apply(celery_app, memory_exporter):
- @celery_app.task
- def fn_task():
- return 42
-
- t = fn_task.apply()
- assert t.successful() is True
- assert t.result == 42
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 1
-
- span = spans[0]
-
- assert span.status.is_ok is True
- assert span.name == "run/test_celery_functional.fn_task"
- assert span.attributes.get("messaging.message_id") == t.task_id
- assert (
- span.attributes.get("celery.task_name")
- == "test_celery_functional.fn_task"
- )
- assert span.attributes.get("celery.action") == "run"
- assert span.attributes.get("celery.state") == "SUCCESS"
-
-
-def test_fn_task_apply_bind(celery_app, memory_exporter):
- @celery_app.task(bind=True)
- def fn_task(self):
- return self
-
- t = fn_task.apply()
- assert t.successful() is True
- assert "fn_task" in t.result.name
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 1
-
- span = spans[0]
-
- assert span.status.is_ok is True
- assert span.name == "run/test_celery_functional.fn_task"
- assert span.attributes.get("messaging.message_id") == t.task_id
- assert (
- span.attributes.get("celery.task_name")
- == "test_celery_functional.fn_task"
- )
- assert span.attributes.get("celery.action") == "run"
- assert span.attributes.get("celery.state") == "SUCCESS"
-
-
-@pytest.mark.skip(reason="inconsistent test results")
-def test_fn_task_apply_async(celery_app, memory_exporter):
- @celery_app.task
- def fn_task_parameters(user, force_logout=False):
- return (user, force_logout)
-
- result = fn_task_parameters.apply_async(
- args=["user"], kwargs={"force_logout": True}
- )
- assert result.get(timeout=ASYNC_GET_TIMEOUT) == ["user", True]
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 2
-
- async_span, run_span = spans
-
- assert run_span.context.trace_id != async_span.context.trace_id
-
- assert async_span.status.is_ok is True
- assert (
- async_span.name
- == "apply_async/test_celery_functional.fn_task_parameters"
- )
- assert async_span.attributes.get("celery.action") == "apply_async"
- assert async_span.attributes.get("messaging.message_id") == result.task_id
- assert (
- async_span.attributes.get("celery.task_name")
- == "test_celery_functional.fn_task_parameters"
- )
-
- assert run_span.status.is_ok is True
- assert run_span.name == "test_celery_functional.fn_task_parameters"
- assert run_span.attributes.get("celery.action") == "run"
- assert run_span.attributes.get("celery.state") == "SUCCESS"
- assert run_span.attributes.get("messaging.message_id") == result.task_id
- assert (
- run_span.attributes.get("celery.task_name")
- == "test_celery_functional.fn_task_parameters"
- )
-
-
-@pytest.mark.skip(reason="inconsistent test results")
-def test_concurrent_delays(celery_app, memory_exporter):
- @celery_app.task
- def fn_task():
- return 42
-
- results = [fn_task.delay() for _ in range(100)]
-
- for result in results:
- assert result.get(timeout=ASYNC_GET_TIMEOUT) == 42
-
- spans = memory_exporter.get_finished_spans()
-
- assert len(spans) == 200
-
-
-@pytest.mark.skip(reason="inconsistent test results")
-def test_fn_task_delay(celery_app, memory_exporter):
- @celery_app.task
- def fn_task_parameters(user, force_logout=False):
- return (user, force_logout)
-
- result = fn_task_parameters.delay("user", force_logout=True)
- assert result.get(timeout=ASYNC_GET_TIMEOUT) == ["user", True]
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 2
-
- async_span, run_span = spans
-
- assert run_span.context.trace_id != async_span.context.trace_id
-
- assert async_span.status.is_ok is True
- assert (
- async_span.name
- == "apply_async/test_celery_functional.fn_task_parameters"
- )
- assert async_span.attributes.get("celery.action") == "apply_async"
- assert async_span.attributes.get("messaging.message_id") == result.task_id
- assert (
- async_span.attributes.get("celery.task_name")
- == "test_celery_functional.fn_task_parameters"
- )
-
- assert run_span.status.is_ok is True
- assert run_span.name == "run/test_celery_functional.fn_task_parameters"
- assert run_span.attributes.get("celery.action") == "run"
- assert run_span.attributes.get("celery.state") == "SUCCESS"
- assert run_span.attributes.get("messaging.message_id") == result.task_id
- assert (
- run_span.attributes.get("celery.task_name")
- == "test_celery_functional.fn_task_parameters"
- )
-
-
-def test_fn_exception(celery_app, memory_exporter):
- @celery_app.task
- def fn_exception():
- raise Exception("Task class is failing")
-
- result = fn_exception.apply()
-
- assert result.failed() is True
- assert "Task class is failing" in result.traceback
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 1
-
- span = spans[0]
-
- assert span.status.is_ok is False
- assert span.name == "run/test_celery_functional.fn_exception"
- assert span.attributes.get("celery.action") == "run"
- assert span.attributes.get("celery.state") == "FAILURE"
- assert (
- span.attributes.get("celery.task_name")
- == "test_celery_functional.fn_exception"
- )
- assert span.status.status_code == StatusCode.ERROR
- assert span.attributes.get("messaging.message_id") == result.task_id
- assert "Task class is failing" in span.status.description
-
-
-def test_fn_exception_expected(celery_app, memory_exporter):
- @celery_app.task(throws=(MyException,))
- def fn_exception():
- raise MyException("Task class is failing")
-
- result = fn_exception.apply()
-
- assert result.failed() is True
- assert "Task class is failing" in result.traceback
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 1
-
- span = spans[0]
-
- assert span.status.is_ok is True
- assert span.status.status_code == StatusCode.UNSET
- assert span.name == "run/test_celery_functional.fn_exception"
- assert span.attributes.get("celery.action") == "run"
- assert span.attributes.get("celery.state") == "FAILURE"
- assert (
- span.attributes.get("celery.task_name")
- == "test_celery_functional.fn_exception"
- )
- assert span.attributes.get("messaging.message_id") == result.task_id
-
-
-def test_fn_retry_exception(celery_app, memory_exporter):
- @celery_app.task
- def fn_exception():
- raise Retry("Task class is being retried")
-
- result = fn_exception.apply()
-
- assert result.failed() is False
- assert "Task class is being retried" in result.traceback
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 1
-
- span = spans[0]
-
- assert span.status.is_ok is True
- assert span.status.status_code == StatusCode.UNSET
- assert span.name == "run/test_celery_functional.fn_exception"
- assert span.attributes.get("celery.action") == "run"
- assert span.attributes.get("celery.state") == "RETRY"
- assert (
- span.attributes.get("celery.task_name")
- == "test_celery_functional.fn_exception"
- )
- assert span.attributes.get("messaging.message_id") == result.task_id
-
-
-def test_class_task(celery_app, memory_exporter):
- class BaseTask(celery_app.Task):
- def run(self):
- return 42
-
- task = BaseTask()
- # register the Task class if it's available (required in Celery 4.0+)
- register_task = getattr(celery_app, "register_task", None)
- if register_task is not None:
- register_task(task)
-
- result = task.apply()
-
- assert result.successful() is True
- assert result.result == 42
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 1
-
- span = spans[0]
-
- assert span.status.is_ok is True
- assert span.name == "run/test_celery_functional.BaseTask"
- assert (
- span.attributes.get("celery.task_name")
- == "test_celery_functional.BaseTask"
- )
- assert span.attributes.get("celery.action") == "run"
- assert span.attributes.get("celery.state") == "SUCCESS"
- assert span.attributes.get("messaging.message_id") == result.task_id
-
-
-def test_class_task_exception(celery_app, memory_exporter):
- class BaseTask(celery_app.Task):
- def run(self):
- raise Exception("Task class is failing")
-
- task = BaseTask()
- # register the Task class if it's available (required in Celery 4.0+)
- register_task = getattr(celery_app, "register_task", None)
- if register_task is not None:
- register_task(task)
-
- result = task.apply()
-
- assert result.failed() is True
- assert "Task class is failing" in result.traceback
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 1
-
- span = spans[0]
-
- assert span.status.is_ok is False
- assert span.name == "run/test_celery_functional.BaseTask"
- assert (
- span.attributes.get("celery.task_name")
- == "test_celery_functional.BaseTask"
- )
- assert span.attributes.get("celery.action") == "run"
- assert span.attributes.get("celery.state") == "FAILURE"
- assert span.status.status_code == StatusCode.ERROR
- assert span.attributes.get("messaging.message_id") == result.task_id
- assert "Task class is failing" in span.status.description
-
-
-def test_class_task_exception_excepted(celery_app, memory_exporter):
- class BaseTask(celery_app.Task):
- throws = (MyException,)
-
- def run(self):
- raise MyException("Task class is failing")
-
- task = BaseTask()
- # register the Task class if it's available (required in Celery 4.0+)
- register_task = getattr(celery_app, "register_task", None)
- if register_task is not None:
- register_task(task)
-
- result = task.apply()
-
- assert result.failed() is True
- assert "Task class is failing" in result.traceback
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 1
-
- span = spans[0]
-
- assert span.status.is_ok is True
- assert span.status.status_code == StatusCode.UNSET
- assert span.name == "run/test_celery_functional.BaseTask"
- assert span.attributes.get("celery.action") == "run"
- assert span.attributes.get("celery.state") == "FAILURE"
- assert span.attributes.get("messaging.message_id") == result.task_id
-
-
-def test_shared_task(celery_app, memory_exporter):
- """Ensure Django Shared Task are supported"""
-
- @celery.shared_task
- def add(x, y):
- return x + y
-
- result = add.apply([2, 2])
- assert result.result == 4
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 1
-
- span = spans[0]
-
- assert span.status.is_ok is True
- assert span.name == "run/test_celery_functional.add"
- assert (
- span.attributes.get("celery.task_name") == "test_celery_functional.add"
- )
- assert span.attributes.get("celery.action") == "run"
- assert span.attributes.get("celery.state") == "SUCCESS"
- assert span.attributes.get("messaging.message_id") == result.task_id
-
-
-@pytest.mark.skip(reason="inconsistent test results")
-def test_apply_async_previous_style_tasks(
- celery_app, celery_worker, memory_exporter
-):
- """Ensures apply_async is properly patched if Celery 1.0 style tasks are
- used even in newer versions. This should extend support to previous versions
- of Celery."""
-
- class CelerySuperClass(celery.task.Task):
- abstract = True
-
- @classmethod
- def apply_async(cls, args=None, kwargs=None, **kwargs_):
- return super(CelerySuperClass, cls).apply_async(
- args=args, kwargs=kwargs, **kwargs_
- )
-
- def run(self, *args, **kwargs):
- if "stop" in kwargs:
- # avoid call loop
- return
- CelerySubClass.apply_async(args=[], kwargs={"stop": True}).get(
- timeout=ASYNC_GET_TIMEOUT
- )
-
- class CelerySubClass(CelerySuperClass):
- pass
-
- celery_worker.reload()
-
- task = CelerySubClass()
- result = task.apply()
-
- spans = memory_exporter.get_finished_spans()
- assert len(spans) == 3
-
- async_span, async_run_span, run_span = spans
-
- assert run_span.status.is_ok is True
- assert run_span.name == "run/test_celery_functional.CelerySubClass"
- assert (
- run_span.attributes.get("celery.task_name")
- == "test_celery_functional.CelerySubClass"
- )
- assert run_span.attributes.get("celery.action") == "run"
- assert run_span.attributes.get("celery.state") == "SUCCESS"
- assert run_span.attributes.get("messaging.message_id") == result.task_id
-
- assert async_run_span.status.is_ok is True
- assert async_run_span.name == "run/test_celery_functional.CelerySubClass"
- assert (
- async_run_span.attributes.get("celery.task_name")
- == "test_celery_functional.CelerySubClass"
- )
- assert async_run_span.attributes.get("celery.action") == "run"
- assert async_run_span.attributes.get("celery.state") == "SUCCESS"
- assert (
- async_run_span.attributes.get("messaging.message_id") != result.task_id
- )
-
- assert async_span.status.is_ok is True
- assert (
- async_span.name == "apply_async/test_celery_functional.CelerySubClass"
- )
- assert (
- async_span.attributes.get("celery.task_name")
- == "test_celery_functional.CelerySubClass"
- )
- assert async_span.attributes.get("celery.action") == "apply_async"
- assert async_span.attributes.get("messaging.message_id") != result.task_id
- assert async_span.attributes.get(
- "messaging.message_id"
- ) == async_run_span.attributes.get("messaging.message_id")
-
-
-def test_custom_tracer_provider(celery_app, memory_exporter):
- @celery_app.task
- def fn_task():
- return 42
-
- resource = resources.Resource.create({})
- tracer_provider = TracerProvider(resource=resource)
- span_processor = export.SimpleExportSpanProcessor(memory_exporter)
- tracer_provider.add_span_processor(span_processor)
-
- trace_api.set_tracer_provider(tracer_provider)
-
- CeleryInstrumentor().uninstrument()
- CeleryInstrumentor().instrument(tracer_provider=tracer_provider)
-
- fn_task.delay()
-
- spans_list = memory_exporter.get_finished_spans()
- assert len(spans_list) == 1
-
- span = spans_list[0]
- assert span.resource == resource
diff --git a/tests/opentelemetry-docker-tests/tests/check_availability.py b/tests/opentelemetry-docker-tests/tests/check_availability.py
deleted file mode 100644
index 30825721934..00000000000
--- a/tests/opentelemetry-docker-tests/tests/check_availability.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# Copyright The OpenTelemetry 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
-import os
-import time
-
-import mysql.connector
-import psycopg2
-import pymongo
-import redis
-
-MONGODB_COLLECTION_NAME = "test"
-MONGODB_DB_NAME = os.getenv("MONGODB_DB_NAME", "opentelemetry-tests")
-MONGODB_HOST = os.getenv("MONGODB_HOST", "localhost")
-MONGODB_PORT = int(os.getenv("MONGODB_PORT", "27017"))
-MYSQL_DB_NAME = os.getenv("MYSQL_DB_NAME ", "opentelemetry-tests")
-MYSQL_HOST = os.getenv("MYSQL_HOST ", "localhost")
-MYSQL_PORT = int(os.getenv("MYSQL_PORT ", "3306"))
-MYSQL_USER = os.getenv("MYSQL_USER ", "testuser")
-MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD ", "testpassword")
-POSTGRES_DB_NAME = os.getenv("POSTGRESQL_DB_NAME", "opentelemetry-tests")
-POSTGRES_HOST = os.getenv("POSTGRESQL_HOST", "localhost")
-POSTGRES_PASSWORD = os.getenv("POSTGRESQL_HOST", "testpassword")
-POSTGRES_PORT = int(os.getenv("POSTGRESQL_PORT", "5432"))
-POSTGRES_USER = os.getenv("POSTGRESQL_HOST", "testuser")
-REDIS_HOST = os.getenv("REDIS_HOST", "localhost")
-REDIS_PORT = int(os.getenv("REDIS_PORT ", "6379"))
-RETRY_COUNT = 8
-RETRY_INTERVAL = 5 # Seconds
-
-logger = logging.getLogger(__name__)
-
-
-def retryable(func):
- def wrapper():
- # Try to connect to DB
- for i in range(RETRY_COUNT):
- try:
- func()
- return
- except Exception as ex: # pylint: disable=broad-except
- logger.error(
- "waiting for %s, retry %d/%d [%s]",
- func.__name__,
- i + 1,
- RETRY_COUNT,
- ex,
- )
- time.sleep(RETRY_INTERVAL)
- raise Exception("waiting for {} failed".format(func.__name__))
-
- return wrapper
-
-
-@retryable
-def check_pymongo_connection():
- client = pymongo.MongoClient(
- MONGODB_HOST, MONGODB_PORT, serverSelectionTimeoutMS=2000
- )
- db = client[MONGODB_DB_NAME]
- collection = db[MONGODB_COLLECTION_NAME]
- collection.find_one()
- client.close()
-
-
-@retryable
-def check_mysql_connection():
- connection = mysql.connector.connect(
- user=MYSQL_USER,
- password=MYSQL_PASSWORD,
- host=MYSQL_HOST,
- port=MYSQL_PORT,
- database=MYSQL_DB_NAME,
- )
- connection.close()
-
-
-@retryable
-def check_postgres_connection():
- connection = psycopg2.connect(
- dbname=POSTGRES_DB_NAME,
- user=POSTGRES_USER,
- password=POSTGRES_PASSWORD,
- host=POSTGRES_HOST,
- port=POSTGRES_PORT,
- )
- connection.close()
-
-
-@retryable
-def check_redis_connection():
- connection = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)
- connection.hgetall("*")
-
-
-def check_docker_services_availability():
- # Check if Docker services accept connections
- check_pymongo_connection()
- check_mysql_connection()
- check_postgres_connection()
- check_redis_connection()
-
-
-check_docker_services_availability()
diff --git a/tests/opentelemetry-docker-tests/tests/docker-compose.yml b/tests/opentelemetry-docker-tests/tests/docker-compose.yml
index bbb005a02ef..c731f83da1a 100644
--- a/tests/opentelemetry-docker-tests/tests/docker-compose.yml
+++ b/tests/opentelemetry-docker-tests/tests/docker-compose.yml
@@ -1,44 +1,6 @@
version: '3'
services:
- otmongo:
- ports:
- - "27017:27017"
- image: mongo:latest
- otmysql:
- ports:
- - "3306:3306"
- image: mysql:latest
- restart: always
- environment:
- MYSQL_USER: testuser
- MYSQL_PASSWORD: testpassword
- MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
- MYSQL_DATABASE: opentelemetry-tests
- otpostgres:
- image: postgres
- ports:
- - "5432:5432"
- environment:
- POSTGRES_USER: testuser
- POSTGRES_PASSWORD: testpassword
- POSTGRES_DB: opentelemetry-tests
- otredis:
- image: redis:4.0-alpine
- ports:
- - "127.0.0.1:6379:6379"
- otjaeger:
- image: jaegertracing/all-in-one:1.8
- environment:
- COLLECTOR_ZIPKIN_HTTP_PORT: "9411"
- ports:
- - "5775:5775/udp"
- - "6831:6831/udp"
- - "6832:6832/udp"
- - "5778:5778"
- - "16686:16686"
- - "14268:14268"
- - "9411:9411"
otopencensus:
image: omnition/opencensus-collector:0.1.11
command: --logging-exporter DEBUG
diff --git a/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py b/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py
deleted file mode 100644
index fc237fe12b0..00000000000
--- a/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import mysql.connector
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.mysql import MySQLInstrumentor
-from opentelemetry.test.test_base import TestBase
-
-MYSQL_USER = os.getenv("MYSQL_USER ", "testuser")
-MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD ", "testpassword")
-MYSQL_HOST = os.getenv("MYSQL_HOST ", "localhost")
-MYSQL_PORT = int(os.getenv("MYSQL_PORT ", "3306"))
-MYSQL_DB_NAME = os.getenv("MYSQL_DB_NAME ", "opentelemetry-tests")
-
-
-class TestFunctionalMysql(TestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls._connection = None
- cls._cursor = None
- cls._tracer = cls.tracer_provider.get_tracer(__name__)
- MySQLInstrumentor().instrument()
-
- @classmethod
- def tearDownClass(cls):
- if cls._connection:
- cls._connection.close()
- MySQLInstrumentor().uninstrument()
-
- def setUp(self):
- super().setUp()
- self._connection = mysql.connector.connect(
- user=MYSQL_USER,
- password=MYSQL_PASSWORD,
- host=MYSQL_HOST,
- port=MYSQL_PORT,
- database=MYSQL_DB_NAME,
- )
- self._cursor = self._connection.cursor()
-
- def validate_spans(self):
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
- for span in spans:
- if span.name == "rootSpan":
- root_span = span
- else:
- db_span = span
- self.assertIsInstance(span.start_time, int)
- self.assertIsInstance(span.end_time, int)
- self.assertIsNotNone(root_span)
- self.assertIsNotNone(db_span)
- self.assertEqual(root_span.name, "rootSpan")
- self.assertEqual(db_span.name, "mysql.opentelemetry-tests")
- self.assertIsNotNone(db_span.parent)
- self.assertIs(db_span.parent, root_span.get_span_context())
- self.assertIs(db_span.kind, trace_api.SpanKind.CLIENT)
- self.assertEqual(db_span.attributes["db.instance"], MYSQL_DB_NAME)
- self.assertEqual(db_span.attributes["net.peer.name"], MYSQL_HOST)
- self.assertEqual(db_span.attributes["net.peer.port"], MYSQL_PORT)
-
- def test_execute(self):
- """Should create a child span for execute"""
- with self._tracer.start_as_current_span("rootSpan"):
- self._cursor.execute("CREATE TABLE IF NOT EXISTS test (id INT)")
- self.validate_spans()
-
- def test_execute_with_connection_context_manager(self):
- """Should create a child span for execute with connection context"""
- with self._tracer.start_as_current_span("rootSpan"):
- with self._connection as conn:
- cursor = conn.cursor()
- cursor.execute("CREATE TABLE IF NOT EXISTS test (id INT)")
- self.validate_spans()
-
- def test_execute_with_cursor_context_manager(self):
- """Should create a child span for execute with cursor context"""
- with self._tracer.start_as_current_span("rootSpan"):
- with self._connection.cursor() as cursor:
- cursor.execute("CREATE TABLE IF NOT EXISTS test (id INT)")
- self.validate_spans()
-
- def test_executemany(self):
- """Should create a child span for executemany"""
- with self._tracer.start_as_current_span("rootSpan"):
- data = (("1",), ("2",), ("3",))
- stmt = "INSERT INTO test (id) VALUES (%s)"
- self._cursor.executemany(stmt, data)
- self.validate_spans()
-
- def test_callproc(self):
- """Should create a child span for callproc"""
- with self._tracer.start_as_current_span("rootSpan"), self.assertRaises(
- Exception
- ):
- self._cursor.callproc("test", ())
- self.validate_spans()
diff --git a/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py b/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py
deleted file mode 100644
index d76cd702ee6..00000000000
--- a/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py
+++ /dev/null
@@ -1,193 +0,0 @@
-# Copyright 2020, OpenTelemetry 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 asyncio
-import os
-
-import aiopg
-import psycopg2
-import pytest
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.aiopg import AiopgInstrumentor
-from opentelemetry.test.test_base import TestBase
-
-POSTGRES_HOST = os.getenv("POSTGRESQL_HOST ", "localhost")
-POSTGRES_PORT = int(os.getenv("POSTGRESQL_PORT ", "5432"))
-POSTGRES_DB_NAME = os.getenv("POSTGRESQL_DB_NAME ", "opentelemetry-tests")
-POSTGRES_PASSWORD = os.getenv("POSTGRESQL_HOST ", "testpassword")
-POSTGRES_USER = os.getenv("POSTGRESQL_HOST ", "testuser")
-
-
-def async_call(coro):
- loop = asyncio.get_event_loop()
- return loop.run_until_complete(coro)
-
-
-class TestFunctionalAiopgConnect(TestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls._connection = None
- cls._cursor = None
- cls._tracer = cls.tracer_provider.get_tracer(__name__)
- AiopgInstrumentor().instrument(tracer_provider=cls.tracer_provider)
- cls._connection = async_call(
- aiopg.connect(
- dbname=POSTGRES_DB_NAME,
- user=POSTGRES_USER,
- password=POSTGRES_PASSWORD,
- host=POSTGRES_HOST,
- port=POSTGRES_PORT,
- )
- )
- cls._cursor = async_call(cls._connection.cursor())
-
- @classmethod
- def tearDownClass(cls):
- if cls._cursor:
- cls._cursor.close()
- if cls._connection:
- cls._connection.close()
- AiopgInstrumentor().uninstrument()
-
- def validate_spans(self):
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
- for span in spans:
- if span.name == "rootSpan":
- root_span = span
- else:
- child_span = span
- self.assertIsInstance(span.start_time, int)
- self.assertIsInstance(span.end_time, int)
- self.assertIsNotNone(root_span)
- self.assertIsNotNone(child_span)
- self.assertEqual(root_span.name, "rootSpan")
- self.assertEqual(child_span.name, "postgresql.opentelemetry-tests")
- self.assertIsNotNone(child_span.parent)
- self.assertIs(child_span.parent, root_span.get_span_context())
- self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT)
- self.assertEqual(
- child_span.attributes["db.instance"], POSTGRES_DB_NAME
- )
- self.assertEqual(child_span.attributes["net.peer.name"], POSTGRES_HOST)
- self.assertEqual(child_span.attributes["net.peer.port"], POSTGRES_PORT)
-
- def test_execute(self):
- """Should create a child span for execute method"""
- with self._tracer.start_as_current_span("rootSpan"):
- async_call(
- self._cursor.execute(
- "CREATE TABLE IF NOT EXISTS test (id integer)"
- )
- )
- self.validate_spans()
-
- def test_executemany(self):
- """Should create a child span for executemany"""
- with pytest.raises(psycopg2.ProgrammingError):
- with self._tracer.start_as_current_span("rootSpan"):
- data = (("1",), ("2",), ("3",))
- stmt = "INSERT INTO test (id) VALUES (%s)"
- async_call(self._cursor.executemany(stmt, data))
- self.validate_spans()
-
- def test_callproc(self):
- """Should create a child span for callproc"""
- with self._tracer.start_as_current_span("rootSpan"), self.assertRaises(
- Exception
- ):
- async_call(self._cursor.callproc("test", ()))
- self.validate_spans()
-
-
-class TestFunctionalAiopgCreatePool(TestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls._connection = None
- cls._cursor = None
- cls._tracer = cls.tracer_provider.get_tracer(__name__)
- AiopgInstrumentor().instrument(tracer_provider=cls.tracer_provider)
- cls._pool = async_call(
- aiopg.create_pool(
- dbname=POSTGRES_DB_NAME,
- user=POSTGRES_USER,
- password=POSTGRES_PASSWORD,
- host=POSTGRES_HOST,
- port=POSTGRES_PORT,
- )
- )
- cls._connection = async_call(cls._pool.acquire())
- cls._cursor = async_call(cls._connection.cursor())
-
- @classmethod
- def tearDownClass(cls):
- if cls._cursor:
- cls._cursor.close()
- if cls._connection:
- cls._connection.close()
- if cls._pool:
- cls._pool.close()
- AiopgInstrumentor().uninstrument()
-
- def validate_spans(self):
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
- for span in spans:
- if span.name == "rootSpan":
- root_span = span
- else:
- child_span = span
- self.assertIsInstance(span.start_time, int)
- self.assertIsInstance(span.end_time, int)
- self.assertIsNotNone(root_span)
- self.assertIsNotNone(child_span)
- self.assertEqual(root_span.name, "rootSpan")
- self.assertEqual(child_span.name, "postgresql.opentelemetry-tests")
- self.assertIsNotNone(child_span.parent)
- self.assertIs(child_span.parent, root_span.get_span_context())
- self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT)
- self.assertEqual(
- child_span.attributes["db.instance"], POSTGRES_DB_NAME
- )
- self.assertEqual(child_span.attributes["net.peer.name"], POSTGRES_HOST)
- self.assertEqual(child_span.attributes["net.peer.port"], POSTGRES_PORT)
-
- def test_execute(self):
- """Should create a child span for execute method"""
- with self._tracer.start_as_current_span("rootSpan"):
- async_call(
- self._cursor.execute(
- "CREATE TABLE IF NOT EXISTS test (id integer)"
- )
- )
- self.validate_spans()
-
- def test_executemany(self):
- """Should create a child span for executemany"""
- with pytest.raises(psycopg2.ProgrammingError):
- with self._tracer.start_as_current_span("rootSpan"):
- data = (("1",), ("2",), ("3",))
- stmt = "INSERT INTO test (id) VALUES (%s)"
- async_call(self._cursor.executemany(stmt, data))
- self.validate_spans()
-
- def test_callproc(self):
- """Should create a child span for callproc"""
- with self._tracer.start_as_current_span("rootSpan"), self.assertRaises(
- Exception
- ):
- async_call(self._cursor.callproc("test", ()))
- self.validate_spans()
diff --git a/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py b/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py
deleted file mode 100644
index 28db4c064f9..00000000000
--- a/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# Copyright 2020, OpenTelemetry 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 os
-
-import psycopg2
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor
-from opentelemetry.test.test_base import TestBase
-
-POSTGRES_HOST = os.getenv("POSTGRESQL_HOST ", "localhost")
-POSTGRES_PORT = int(os.getenv("POSTGRESQL_PORT ", "5432"))
-POSTGRES_DB_NAME = os.getenv("POSTGRESQL_DB_NAME ", "opentelemetry-tests")
-POSTGRES_PASSWORD = os.getenv("POSTGRESQL_HOST ", "testpassword")
-POSTGRES_USER = os.getenv("POSTGRESQL_HOST ", "testuser")
-
-
-class TestFunctionalPsycopg(TestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls._connection = None
- cls._cursor = None
- cls._tracer = cls.tracer_provider.get_tracer(__name__)
- Psycopg2Instrumentor().instrument(tracer_provider=cls.tracer_provider)
- cls._connection = psycopg2.connect(
- dbname=POSTGRES_DB_NAME,
- user=POSTGRES_USER,
- password=POSTGRES_PASSWORD,
- host=POSTGRES_HOST,
- port=POSTGRES_PORT,
- )
- cls._connection.set_session(autocommit=True)
- cls._cursor = cls._connection.cursor()
-
- @classmethod
- def tearDownClass(cls):
- if cls._cursor:
- cls._cursor.close()
- if cls._connection:
- cls._connection.close()
- Psycopg2Instrumentor().uninstrument()
-
- def validate_spans(self):
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
- for span in spans:
- if span.name == "rootSpan":
- root_span = span
- else:
- child_span = span
- self.assertIsInstance(span.start_time, int)
- self.assertIsInstance(span.end_time, int)
- self.assertIsNotNone(root_span)
- self.assertIsNotNone(child_span)
- self.assertEqual(root_span.name, "rootSpan")
- self.assertEqual(child_span.name, "postgresql.opentelemetry-tests")
- self.assertIsNotNone(child_span.parent)
- self.assertIs(child_span.parent, root_span.get_span_context())
- self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT)
- self.assertEqual(
- child_span.attributes["db.instance"], POSTGRES_DB_NAME
- )
- self.assertEqual(child_span.attributes["net.peer.name"], POSTGRES_HOST)
- self.assertEqual(child_span.attributes["net.peer.port"], POSTGRES_PORT)
-
- def test_execute(self):
- """Should create a child span for execute method"""
- with self._tracer.start_as_current_span("rootSpan"):
- self._cursor.execute(
- "CREATE TABLE IF NOT EXISTS test (id integer)"
- )
- self.validate_spans()
-
- def test_execute_with_connection_context_manager(self):
- """Should create a child span for execute with connection context"""
- with self._tracer.start_as_current_span("rootSpan"):
- with self._connection as conn:
- cursor = conn.cursor()
- cursor.execute("CREATE TABLE IF NOT EXISTS test (id INT)")
- self.validate_spans()
-
- def test_execute_with_cursor_context_manager(self):
- """Should create a child span for execute with cursor context"""
- with self._tracer.start_as_current_span("rootSpan"):
- with self._connection.cursor() as cursor:
- cursor.execute("CREATE TABLE IF NOT EXISTS test (id INT)")
- self.validate_spans()
- self.assertTrue(cursor.closed)
-
- def test_executemany(self):
- """Should create a child span for executemany"""
- with self._tracer.start_as_current_span("rootSpan"):
- data = (("1",), ("2",), ("3",))
- stmt = "INSERT INTO test (id) VALUES (%s)"
- self._cursor.executemany(stmt, data)
- self.validate_spans()
-
- def test_callproc(self):
- """Should create a child span for callproc"""
- with self._tracer.start_as_current_span("rootSpan"), self.assertRaises(
- Exception
- ):
- self._cursor.callproc("test", ())
- self.validate_spans()
diff --git a/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py b/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py
deleted file mode 100644
index 577477a2aba..00000000000
--- a/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-from pymongo import MongoClient
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.pymongo import PymongoInstrumentor
-from opentelemetry.test.test_base import TestBase
-
-MONGODB_HOST = os.getenv("MONGODB_HOST ", "localhost")
-MONGODB_PORT = int(os.getenv("MONGODB_PORT ", "27017"))
-MONGODB_DB_NAME = os.getenv("MONGODB_DB_NAME ", "opentelemetry-tests")
-MONGODB_COLLECTION_NAME = "test"
-
-
-class TestFunctionalPymongo(TestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls._tracer = cls.tracer_provider.get_tracer(__name__)
- PymongoInstrumentor().instrument()
- client = MongoClient(
- MONGODB_HOST, MONGODB_PORT, serverSelectionTimeoutMS=2000
- )
- db = client[MONGODB_DB_NAME]
- cls._collection = db[MONGODB_COLLECTION_NAME]
-
- def validate_spans(self):
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
- for span in spans:
- if span.name == "rootSpan":
- root_span = span
- else:
- pymongo_span = span
- self.assertIsInstance(span.start_time, int)
- self.assertIsInstance(span.end_time, int)
- self.assertIsNot(root_span, None)
- self.assertIsNot(pymongo_span, None)
- self.assertIsNotNone(pymongo_span.parent)
- self.assertIs(pymongo_span.parent, root_span.get_span_context())
- self.assertIs(pymongo_span.kind, trace_api.SpanKind.CLIENT)
- self.assertEqual(
- pymongo_span.attributes["db.instance"], MONGODB_DB_NAME
- )
- self.assertEqual(
- pymongo_span.attributes["net.peer.name"], MONGODB_HOST
- )
- self.assertEqual(
- pymongo_span.attributes["net.peer.port"], MONGODB_PORT
- )
-
- def test_insert(self):
- """Should create a child span for insert"""
- with self._tracer.start_as_current_span("rootSpan"):
- self._collection.insert_one(
- {"name": "testName", "value": "testValue"}
- )
- self.validate_spans()
-
- def test_update(self):
- """Should create a child span for update"""
- with self._tracer.start_as_current_span("rootSpan"):
- self._collection.update_one(
- {"name": "testName"}, {"$set": {"value": "someOtherValue"}}
- )
- self.validate_spans()
-
- def test_find(self):
- """Should create a child span for find"""
- with self._tracer.start_as_current_span("rootSpan"):
- self._collection.find_one()
- self.validate_spans()
-
- def test_delete(self):
- """Should create a child span for delete"""
- with self._tracer.start_as_current_span("rootSpan"):
- self._collection.delete_one({"name": "testName"})
- self.validate_spans()
-
- def test_uninstrument(self):
- # check that integration is working
- self._collection.find_one()
- spans = self.memory_exporter.get_finished_spans()
- self.memory_exporter.clear()
- self.assertEqual(len(spans), 1)
-
- # uninstrument and check not new spans are created
- PymongoInstrumentor().uninstrument()
- self._collection.find_one()
- spans = self.memory_exporter.get_finished_spans()
- self.memory_exporter.clear()
- self.assertEqual(len(spans), 0)
-
- # re-enable and check that it works again
- PymongoInstrumentor().instrument()
- self._collection.find_one()
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
diff --git a/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py b/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py
deleted file mode 100644
index 7c09025551d..00000000000
--- a/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-
-import pymysql as pymy
-
-from opentelemetry import trace as trace_api
-from opentelemetry.instrumentation.pymysql import PyMySQLInstrumentor
-from opentelemetry.test.test_base import TestBase
-
-MYSQL_USER = os.getenv("MYSQL_USER ", "testuser")
-MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD ", "testpassword")
-MYSQL_HOST = os.getenv("MYSQL_HOST ", "localhost")
-MYSQL_PORT = int(os.getenv("MYSQL_PORT ", "3306"))
-MYSQL_DB_NAME = os.getenv("MYSQL_DB_NAME ", "opentelemetry-tests")
-
-
-class TestFunctionalPyMysql(TestBase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls._connection = None
- cls._cursor = None
- cls._tracer = cls.tracer_provider.get_tracer(__name__)
- PyMySQLInstrumentor().instrument()
- cls._connection = pymy.connect(
- user=MYSQL_USER,
- password=MYSQL_PASSWORD,
- host=MYSQL_HOST,
- port=MYSQL_PORT,
- database=MYSQL_DB_NAME,
- )
- cls._cursor = cls._connection.cursor()
-
- @classmethod
- def tearDownClass(cls):
- if cls._connection:
- cls._connection.close()
- PyMySQLInstrumentor().uninstrument()
-
- def validate_spans(self):
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
- for span in spans:
- if span.name == "rootSpan":
- root_span = span
- else:
- db_span = span
- self.assertIsInstance(span.start_time, int)
- self.assertIsInstance(span.end_time, int)
- self.assertIsNotNone(root_span)
- self.assertIsNotNone(db_span)
- self.assertEqual(root_span.name, "rootSpan")
- self.assertEqual(db_span.name, "mysql.opentelemetry-tests")
- self.assertIsNotNone(db_span.parent)
- self.assertIs(db_span.parent, root_span.get_span_context())
- self.assertIs(db_span.kind, trace_api.SpanKind.CLIENT)
- self.assertEqual(db_span.attributes["db.instance"], MYSQL_DB_NAME)
- self.assertEqual(db_span.attributes["net.peer.name"], MYSQL_HOST)
- self.assertEqual(db_span.attributes["net.peer.port"], MYSQL_PORT)
-
- def test_execute(self):
- """Should create a child span for execute"""
- with self._tracer.start_as_current_span("rootSpan"):
- self._cursor.execute("CREATE TABLE IF NOT EXISTS test (id INT)")
- self.validate_spans()
-
- def test_execute_with_cursor_context_manager(self):
- """Should create a child span for execute with cursor context"""
- with self._tracer.start_as_current_span("rootSpan"):
- with self._connection.cursor() as cursor:
- cursor.execute("CREATE TABLE IF NOT EXISTS test (id INT)")
- self.validate_spans()
-
- def test_executemany(self):
- """Should create a child span for executemany"""
- with self._tracer.start_as_current_span("rootSpan"):
- data = (("1",), ("2",), ("3",))
- stmt = "INSERT INTO test (id) VALUES (%s)"
- self._cursor.executemany(stmt, data)
- self.validate_spans()
-
- def test_callproc(self):
- """Should create a child span for callproc"""
- with self._tracer.start_as_current_span("rootSpan"), self.assertRaises(
- Exception
- ):
- self._cursor.callproc("test", ())
- self.validate_spans()
diff --git a/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py b/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py
deleted file mode 100644
index 8bdc120105b..00000000000
--- a/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright The OpenTelemetry 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 redis
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.redis import RedisInstrumentor
-from opentelemetry.test.test_base import TestBase
-
-
-class TestRedisInstrument(TestBase):
-
- test_service = "redis"
-
- def setUp(self):
- super().setUp()
- self.redis_client = redis.Redis(port=6379)
- self.redis_client.flushall()
- RedisInstrumentor().instrument(tracer_provider=self.tracer_provider)
-
- def tearDown(self):
- super().tearDown()
- RedisInstrumentor().uninstrument()
-
- def _check_span(self, span):
- self.assertEqual(span.attributes["service"], self.test_service)
- self.assertEqual(span.name, "redis.command")
- self.assertIs(span.status.status_code, trace.status.StatusCode.UNSET)
- self.assertEqual(span.attributes.get("db.instance"), 0)
- self.assertEqual(
- span.attributes.get("db.url"), "redis://localhost:6379"
- )
-
- def test_long_command(self):
- self.redis_client.mget(*range(1000))
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self._check_span(span)
- self.assertTrue(
- span.attributes.get("db.statement").startswith("MGET 0 1 2 3")
- )
- self.assertTrue(span.attributes.get("db.statement").endswith("..."))
-
- def test_basics(self):
- self.assertIsNone(self.redis_client.get("cheese"))
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self._check_span(span)
- self.assertEqual(span.attributes.get("db.statement"), "GET cheese")
- self.assertEqual(span.attributes.get("redis.args_length"), 2)
-
- def test_pipeline_traced(self):
- with self.redis_client.pipeline(transaction=False) as pipeline:
- pipeline.set("blah", 32)
- pipeline.rpush("foo", "éé")
- pipeline.hgetall("xxx")
- pipeline.execute()
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self._check_span(span)
- self.assertEqual(
- span.attributes.get("db.statement"),
- "SET blah 32\nRPUSH foo éé\nHGETALL xxx",
- )
- self.assertEqual(span.attributes.get("redis.pipeline_length"), 3)
-
- def test_pipeline_immediate(self):
- with self.redis_client.pipeline() as pipeline:
- pipeline.set("a", 1)
- pipeline.immediate_execute_command("SET", "b", 2)
- pipeline.execute()
-
- spans = self.memory_exporter.get_finished_spans()
- # expecting two separate spans here, rather than a
- # single span for the whole pipeline
- self.assertEqual(len(spans), 2)
- span = spans[0]
- self._check_span(span)
- self.assertEqual(span.attributes.get("db.statement"), "SET b 2")
-
- def test_parent(self):
- """Ensure OpenTelemetry works with redis."""
- ot_tracer = trace.get_tracer("redis_svc")
-
- with ot_tracer.start_as_current_span("redis_get"):
- self.assertIsNone(self.redis_client.get("cheese"))
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
- child_span, parent_span = spans[0], spans[1]
-
- # confirm the parenting
- self.assertIsNone(parent_span.parent)
- self.assertIs(child_span.parent, parent_span.get_span_context())
-
- self.assertEqual(parent_span.name, "redis_get")
- self.assertEqual(parent_span.instrumentation_info.name, "redis_svc")
-
- self.assertEqual(
- child_span.attributes.get("service"), self.test_service
- )
- self.assertEqual(child_span.name, "redis.command")
diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/__init__.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/__init__.py
deleted file mode 100644
index b0a6f428417..00000000000
--- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright The OpenTelemetry 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/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py
deleted file mode 100644
index 72137f83e84..00000000000
--- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# Copyright The OpenTelemetry 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 contextlib
-
-from sqlalchemy import Column, Integer, String, create_engine
-from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy.orm import sessionmaker
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
-from opentelemetry.instrumentation.sqlalchemy.engine import _DB, _ROWS, _STMT
-from opentelemetry.test.test_base import TestBase
-
-Base = declarative_base()
-
-
-def _create_engine(engine_args):
- # create a SQLAlchemy engine
- config = dict(engine_args)
- url = config.pop("url")
- return create_engine(url, **config)
-
-
-class Player(Base):
- """Player entity used to test SQLAlchemy ORM"""
-
- __tablename__ = "players"
-
- id = Column(Integer, primary_key=True)
- name = Column(String(20))
-
-
-class SQLAlchemyTestMixin(TestBase):
- __test__ = False
-
- """SQLAlchemy test mixin that includes a complete set of tests
- that must be executed for different engine. When a new test (or
- a regression test) should be added to SQLAlchemy test suite, a new
- entry must be appended here so that it will be executed for all
- available and supported engines. If the test is specific to only
- one engine, that test must be added to the specific `TestCase`
- implementation.
-
- To support a new engine, create a new `TestCase` that inherits from
- `SQLAlchemyTestMixin` and `TestCase`. Then you must define the following
- static class variables:
- * VENDOR: the database vendor name
- * SQL_DB: the `db.type` tag that we expect (it's the name of the database available in the `.env` file)
- * SERVICE: the service that we expect by default
- * ENGINE_ARGS: all arguments required to create the engine
-
- To check specific tags in each test, you must implement the
- `check_meta(self, span)` method.
- """
-
- VENDOR = None
- SQL_DB = None
- SERVICE = None
- ENGINE_ARGS = None
-
- @contextlib.contextmanager
- def connection(self):
- # context manager that provides a connection
- # to the underlying database
- try:
- conn = self.engine.connect()
- yield conn
- finally:
- conn.close()
-
- def check_meta(self, span):
- """function that can be implemented according to the
- specific engine implementation
- """
-
- def setUp(self):
- super().setUp()
- # create an engine with the given arguments
- self.engine = _create_engine(self.ENGINE_ARGS)
-
- # create the database / entities and prepare a session for the test
- Base.metadata.drop_all(bind=self.engine)
- Base.metadata.create_all(self.engine, checkfirst=False)
- self.session = sessionmaker(bind=self.engine)()
- # trace the engine
- SQLAlchemyInstrumentor().instrument(
- engine=self.engine, tracer_provider=self.tracer_provider
- )
- self.memory_exporter.clear()
-
- def tearDown(self):
- # pylint: disable=invalid-name
- # clear the database and dispose the engine
- self.session.close()
- Base.metadata.drop_all(bind=self.engine)
- self.engine.dispose()
- SQLAlchemyInstrumentor().uninstrument()
- super().tearDown()
-
- def _check_span(self, span):
- self.assertEqual(span.name, "{}.query".format(self.VENDOR))
- self.assertEqual(span.attributes.get("service"), self.SERVICE)
- self.assertEqual(span.attributes.get(_DB), self.SQL_DB)
- self.assertIs(span.status.status_code, trace.status.StatusCode.UNSET)
- self.assertGreater((span.end_time - span.start_time), 0)
-
- def test_orm_insert(self):
- # ensures that the ORM session is traced
- wayne = Player(id=1, name="wayne")
- self.session.add(wayne)
- self.session.commit()
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self._check_span(span)
- self.assertIn("INSERT INTO players", span.attributes.get(_STMT))
- self.assertEqual(span.attributes.get(_ROWS), 1)
- self.check_meta(span)
-
- def test_session_query(self):
- # ensures that the Session queries are traced
- out = list(self.session.query(Player).filter_by(name="wayne"))
- self.assertEqual(len(out), 0)
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self._check_span(span)
- self.assertIn(
- "SELECT players.id AS players_id, players.name AS players_name \nFROM players \nWHERE players.name",
- span.attributes.get(_STMT),
- )
- self.check_meta(span)
-
- def test_engine_connect_execute(self):
- # ensures that engine.connect() is properly traced
- with self.connection() as conn:
- rows = conn.execute("SELECT * FROM players").fetchall()
- self.assertEqual(len(rows), 0)
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- self._check_span(span)
- self.assertEqual(span.attributes.get(_STMT), "SELECT * FROM players")
- self.check_meta(span)
-
- def test_parent(self):
- """Ensure that sqlalchemy works with opentelemetry."""
- tracer = self.tracer_provider.get_tracer("sqlalch_svc")
-
- with tracer.start_as_current_span("sqlalch_op"):
- with self.connection() as conn:
- rows = conn.execute("SELECT * FROM players").fetchall()
- self.assertEqual(len(rows), 0)
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 2)
- child_span, parent_span = spans
-
- # confirm the parenting
- self.assertIsNone(parent_span.parent)
- self.assertIs(child_span.parent, parent_span.get_span_context())
-
- self.assertEqual(parent_span.name, "sqlalch_op")
- self.assertEqual(parent_span.instrumentation_info.name, "sqlalch_svc")
-
- self.assertEqual(child_span.name, "{}.query".format(self.VENDOR))
- self.assertEqual(child_span.attributes.get("service"), self.SERVICE)
diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_instrument.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_instrument.py
deleted file mode 100644
index c408c63d943..00000000000
--- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_instrument.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-import unittest
-
-import sqlalchemy
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
-from opentelemetry.test.test_base import TestBase
-
-POSTGRES_CONFIG = {
- "host": "127.0.0.1",
- "port": int(os.getenv("TEST_POSTGRES_PORT", "5432")),
- "user": os.getenv("TEST_POSTGRES_USER", "testuser"),
- "password": os.getenv("TEST_POSTGRES_PASSWORD", "testpassword"),
- "dbname": os.getenv("TEST_POSTGRES_DB", "opentelemetry-tests"),
-}
-
-
-class SQLAlchemyInstrumentTestCase(TestBase):
- """TestCase that checks if the engine is properly traced
- when the `instrument()` method is used.
- """
-
- def setUp(self):
- # create a traced engine with the given arguments
- SQLAlchemyInstrumentor().instrument()
- dsn = (
- "postgresql://%(user)s:%(password)s@%(host)s:%(port)s/%(dbname)s"
- % POSTGRES_CONFIG
- )
- self.engine = sqlalchemy.create_engine(dsn)
-
- # prepare a connection
- self.conn = self.engine.connect()
- super().setUp()
-
- def tearDown(self):
- # clear the database and dispose the engine
- self.conn.close()
- self.engine.dispose()
- SQLAlchemyInstrumentor().uninstrument()
-
- def test_engine_traced(self):
- # ensures that the engine is traced
- rows = self.conn.execute("SELECT 1").fetchall()
- self.assertEqual(len(rows), 1)
-
- traces = self.memory_exporter.get_finished_spans()
- # trace composition
- self.assertEqual(len(traces), 1)
- span = traces[0]
- # check subset of span fields
- self.assertEqual(span.name, "postgres.query")
- self.assertEqual(span.attributes.get("service"), "postgres")
- self.assertIs(span.status.status_code, trace.status.StatusCode.UNSET)
- self.assertGreater((span.end_time - span.start_time), 0)
diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py
deleted file mode 100644
index 310cd91f732..00000000000
--- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-import unittest
-
-import pytest
-from sqlalchemy.exc import ProgrammingError
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.sqlalchemy.engine import (
- _DB,
- _HOST,
- _PORT,
- _ROWS,
- _STMT,
-)
-
-from .mixins import SQLAlchemyTestMixin
-
-MYSQL_CONFIG = {
- "host": "127.0.0.1",
- "port": int(os.getenv("TEST_MYSQL_PORT", "3306")),
- "user": os.getenv("TEST_MYSQL_USER", "testuser"),
- "password": os.getenv("TEST_MYSQL_PASSWORD", "testpassword"),
- "database": os.getenv("TEST_MYSQL_DATABASE", "opentelemetry-tests"),
-}
-
-
-class MysqlConnectorTestCase(SQLAlchemyTestMixin):
- """TestCase for mysql-connector engine"""
-
- __test__ = True
-
- VENDOR = "mysql"
- SQL_DB = "opentelemetry-tests"
- SERVICE = "mysql"
- ENGINE_ARGS = {
- "url": "mysql+mysqlconnector://%(user)s:%(password)s@%(host)s:%(port)s/%(database)s"
- % MYSQL_CONFIG
- }
-
- def check_meta(self, span):
- # check database connection tags
- self.assertEqual(span.attributes.get(_HOST), MYSQL_CONFIG["host"])
- self.assertEqual(span.attributes.get(_PORT), MYSQL_CONFIG["port"])
-
- def test_engine_execute_errors(self):
- # ensures that SQL errors are reported
- with pytest.raises(ProgrammingError):
- with self.connection() as conn:
- conn.execute("SELECT * FROM a_wrong_table").fetchall()
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- # span fields
- self.assertEqual(span.name, "{}.query".format(self.VENDOR))
- self.assertEqual(span.attributes.get("service"), self.SERVICE)
- self.assertEqual(
- span.attributes.get(_STMT), "SELECT * FROM a_wrong_table"
- )
- self.assertEqual(span.attributes.get(_DB), self.SQL_DB)
- self.assertIsNone(span.attributes.get(_ROWS))
- self.check_meta(span)
- self.assertTrue(span.end_time - span.start_time > 0)
- # check the error
- self.assertIs(
- span.status.status_code, trace.status.StatusCode.ERROR,
- )
- self.assertIn("a_wrong_table", span.status.description)
diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py
deleted file mode 100644
index 91fb123c97a..00000000000
--- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright The OpenTelemetry 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 os
-import unittest
-
-import psycopg2
-import pytest
-from sqlalchemy.exc import ProgrammingError
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.sqlalchemy.engine import (
- _DB,
- _HOST,
- _PORT,
- _ROWS,
- _STMT,
-)
-
-from .mixins import SQLAlchemyTestMixin
-
-POSTGRES_CONFIG = {
- "host": "127.0.0.1",
- "port": int(os.getenv("TEST_POSTGRES_PORT", "5432")),
- "user": os.getenv("TEST_POSTGRES_USER", "testuser"),
- "password": os.getenv("TEST_POSTGRES_PASSWORD", "testpassword"),
- "dbname": os.getenv("TEST_POSTGRES_DB", "opentelemetry-tests"),
-}
-
-
-class PostgresTestCase(SQLAlchemyTestMixin):
- """TestCase for Postgres Engine"""
-
- __test__ = True
-
- VENDOR = "postgres"
- SQL_DB = "opentelemetry-tests"
- SERVICE = "postgres"
- ENGINE_ARGS = {
- "url": "postgresql://%(user)s:%(password)s@%(host)s:%(port)s/%(dbname)s"
- % POSTGRES_CONFIG
- }
-
- def check_meta(self, span):
- # check database connection tags
- self.assertEqual(span.attributes.get(_HOST), POSTGRES_CONFIG["host"])
- self.assertEqual(span.attributes.get(_PORT), POSTGRES_CONFIG["port"])
-
- def test_engine_execute_errors(self):
- # ensures that SQL errors are reported
- with pytest.raises(ProgrammingError):
- with self.connection() as conn:
- conn.execute("SELECT * FROM a_wrong_table").fetchall()
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- # span fields
- self.assertEqual(span.name, "{}.query".format(self.VENDOR))
- self.assertEqual(span.attributes.get("service"), self.SERVICE)
- self.assertEqual(
- span.attributes.get(_STMT), "SELECT * FROM a_wrong_table"
- )
- self.assertEqual(span.attributes.get(_DB), self.SQL_DB)
- self.assertIsNone(span.attributes.get(_ROWS))
- self.check_meta(span)
- self.assertTrue(span.end_time - span.start_time > 0)
- # check the error
- self.assertIs(
- span.status.status_code, trace.status.StatusCode.ERROR,
- )
- self.assertIn("a_wrong_table", span.status.description)
-
-
-class PostgresCreatorTestCase(PostgresTestCase):
- """TestCase for Postgres Engine that includes the same tests set
- of `PostgresTestCase`, but it uses a specific `creator` function.
- """
-
- VENDOR = "postgres"
- SQL_DB = "opentelemetry-tests"
- SERVICE = "postgres"
- ENGINE_ARGS = {
- "url": "postgresql://",
- "creator": lambda: psycopg2.connect(**POSTGRES_CONFIG),
- }
diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_sqlite.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_sqlite.py
deleted file mode 100644
index 309dd73ccc7..00000000000
--- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_sqlite.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright The OpenTelemetry 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 unittest
-
-import pytest
-from sqlalchemy.exc import OperationalError
-
-from opentelemetry import trace
-from opentelemetry.instrumentation.sqlalchemy.engine import _DB, _ROWS, _STMT
-
-from .mixins import SQLAlchemyTestMixin
-
-
-class SQLiteTestCase(SQLAlchemyTestMixin):
- """TestCase for the SQLite engine"""
-
- __test__ = True
-
- VENDOR = "sqlite"
- SQL_DB = ":memory:"
- SERVICE = "sqlite"
- ENGINE_ARGS = {"url": "sqlite:///:memory:"}
-
- def test_engine_execute_errors(self):
- # ensures that SQL errors are reported
- with pytest.raises(OperationalError):
- with self.connection() as conn:
- conn.execute("SELECT * FROM a_wrong_table").fetchall()
-
- spans = self.memory_exporter.get_finished_spans()
- self.assertEqual(len(spans), 1)
- span = spans[0]
- # span fields
- self.assertEqual(span.name, "{}.query".format(self.VENDOR))
- self.assertEqual(span.attributes.get("service"), self.SERVICE)
- self.assertEqual(
- span.attributes.get(_STMT), "SELECT * FROM a_wrong_table"
- )
- self.assertEqual(span.attributes.get(_DB), self.SQL_DB)
- self.assertIsNone(span.attributes.get(_ROWS))
- self.assertTrue((span.end_time - span.start_time) > 0)
- # check the error
- self.assertIs(
- span.status.status_code, trace.status.StatusCode.ERROR,
- )
- self.assertEqual(
- span.status.description, "no such table: a_wrong_table"
- )
diff --git a/tox.ini b/tox.ini
index 806656ced2c..7af7f7ad296 100644
--- a/tox.ini
+++ b/tox.ini
@@ -28,71 +28,10 @@ envlist =
py3{5,6,7,8}-test-instrumentation-example-app
pypy3-test-instrumentation-example-app
- ; opentelemetry-instrumentation-aiohttp-client
- py3{5,6,7,8}-test-instrumentation-aiohttp-client
- pypy3-test-instrumentation-aiohttp-client
-
- ; opentelemetry-instrumentation-aiopg
- py3{5,6,7,8}-test-instrumentation-aiopg
- ; instrumentation-aiopg intentionally excluded from pypy3
-
- ; opentelemetry-instrumentation-botocore
- py3{6,7,8}-test-instrumentation-botocore
- pypy3-test-instrumentation-botocore
-
- ; opentelemetry-instrumentation-django
- py3{5,6,7,8}-test-instrumentation-django
- pypy3-test-instrumentation-django
-
- ; opentelemetry-instrumentation-dbapi
- py3{5,6,7,8}-test-instrumentation-dbapi
- pypy3-test-instrumentation-dbapi
-
- ; opentelemetry-instrumentation-boto
- py3{5,6,7,8}-test-instrumentation-boto
- pypy3-test-instrumentation-boto
-
- ; opentelemetry-instrumentation-elasticsearch
- py3{5,6,7,8}-test-instrumentation-elasticsearch{2,5,6,7}
- pypy3-test-instrumentation-elasticsearch{2,5,6,7}
-
- ; opentelemetry-instrumentation-falcon
- py3{4,5,6,7,8}-test-instrumentation-falcon
- pypy3-test-instrumentation-falcon
-
- ; opentelemetry-instrumentation-fastapi
- ; fastapi only supports 3.6 and above.
- py3{6,7,8}-test-instrumentation-fastapi
- pypy3-test-instrumentation-fastapi
-
- ; opentelemetry-instrumentation-flask
- py3{5,6,7,8}-test-instrumentation-flask
- pypy3-test-instrumentation-flask
-
- ; opentelemetry-instrumentation-requests
- py3{5,6,7,8}-test-instrumentation-requests
- pypy3-test-instrumentation-requests
-
- ; opentelemetry-instrumentation-starlette.
- ; starlette only supports 3.6 and above.
- py3{6,7,8}-test-instrumentation-starlette
- pypy3-test-instrumentation-starlette
-
- ; opentelemetry-instrumentation-jinja2
- py3{5,6,7,8}-test-instrumentation-jinja2
- pypy3-test-instrumentation-jinja2
-
; opentelemetry-exporter-jaeger
py3{5,6,7,8}-test-exporter-jaeger
pypy3-test-exporter-jaeger
- ; opentelemetry-exporter-datadog
- py3{5,6,7,8}-test-exporter-datadog
-
- ; opentelemetry-instrumentation-mysql
- py3{5,6,7,8}-test-instrumentation-mysql
- pypy3-test-instrumentation-mysql
-
; opentelemetry-exporter-opencensus
py3{5,6,7,8}-test-exporter-opencensus
; exporter-opencensus intentionally excluded from pypy3
@@ -105,42 +44,6 @@ envlist =
py3{5,6,7,8}-test-exporter-prometheus
pypy3-test-exporter-prometheus
- ; opentelemetry-instrumentation-psycopg2
- py3{5,6,7,8}-test-instrumentation-psycopg2
- ; ext-psycopg2 intentionally excluded from pypy3
-
- ; opentelemetry-instrumentation-pymemcache
- py3{5,6,7,8}-test-instrumentation-pymemcache
- pypy3-test-instrumentation-pymemcache
-
- ; opentelemetry-instrumentation-pymongo
- py3{5,6,7,8}-test-instrumentation-pymongo
- pypy3-test-instrumentation-pymongo
-
- ; opentelemetry-instrumentation-pymysql
- py3{5,6,7,8}-test-instrumentation-pymysql
- pypy3-test-instrumentation-pymysql
-
- ; opentelemetry-instrumentation-pyramid
- py3{5,6,7,8}-test-instrumentation-pyramid
- pypy3-test-instrumentation-pyramid
-
- ; opentelemetry-instrumentation-asgi
- py3{5,6,7,8}-test-instrumentation-asgi
- pypy3-test-instrumentation-asgi
-
- ; opentelemetry-instrumentation-asyncpg
- py3{5,6,7,8}-test-instrumentation-asyncpg
- ; ext-asyncpg intentionally excluded from pypy3
-
- ; opentelemetry-instrumentation-sqlite3
- py3{5,6,7,8}-test-instrumentation-sqlite3
- pypy3-test-instrumentation-sqlite3
-
- ; opentelemetry-instrumentation-wsgi
- py3{5,6,7,8}-test-instrumentation-wsgi
- pypy3-test-instrumentation-wsgi
-
; opentelemetry-exporter-zipkin
py3{5,6,7,8}-test-exporter-zipkin
pypy3-test-exporter-zipkin
@@ -149,31 +52,6 @@ envlist =
py3{5,6,7,8}-test-core-opentracing-shim
pypy3-test-core-opentracing-shim
- ; opentelemetry-instrumentation-grpc
- py3{5,6,7,8}-test-instrumentation-grpc
-
- ; opentelemetry-instrumentation-sqlalchemy
- py3{5,6,7,8}-test-instrumentation-sqlalchemy
- pypy3-test-instrumentation-sqlalchemy
-
- ; opentelemetry-instrumentation-redis
- py3{5,6,7,8}-test-instrumentation-redis
- pypy3-test-instrumentation-redis
-
- ; opentelemetry-instrumentation-celery
- py3{5,6,7,8}-test-instrumentation-celery
- pypy3-test-instrumentation-celery
-
- ; opentelemetry-instrumentation-system-metrics
- py3{5,6,7,8}-test-instrumentation-system-metrics
- ; instrumentation-system-metrics intentionally excluded from pypy3
- ; known limitation: gc.get_count won't work under pypy
-
- ; opentelemetry-instrumentation-tornado
- ; instrumentation supports >=6 on Py 3.5 and above.
- py3{5,6,7,8}-test-instrumentation-tornado
- pypy3-test-instrumentation-tornado
-
lint
py38-tracecontext
py38-{mypy,mypyinstalled}
@@ -187,14 +65,6 @@ deps =
coverage: pytest
coverage: pytest-cov
mypy,mypyinstalled: mypy
- elasticsearch2: elasticsearch-dsl>=2.0,<3.0
- elasticsearch2: elasticsearch>=2.0,<3.0
- elasticsearch5: elasticsearch-dsl>=5.0,<6.0
- elasticsearch5: elasticsearch>=5.0,<6.0
- elasticsearch6: elasticsearch-dsl>=6.0,<7.0
- elasticsearch6: elasticsearch>=6.0,<7.0
- elasticsearch7: elasticsearch-dsl>=7.0,<8.0
- elasticsearch7: elasticsearch>=7.0,<8.0
setenv = mypy: MYPYPATH={toxinidir}/opentelemetry-api/src/
@@ -204,41 +74,8 @@ changedir =
test-core-proto: opentelemetry-proto/tests
test-core-instrumentation: opentelemetry-instrumentation/tests
test-core-getting-started: docs/getting_started/tests
- test-core-opentracing-shim: instrumentation/opentelemetry-instrumentation-opentracing-shim/tests
-
- test-instrumentation-aiohttp-client: instrumentation/opentelemetry-instrumentation-aiohttp-client/tests
- test-instrumentation-aiopg: instrumentation/opentelemetry-instrumentation-aiopg/tests
- test-instrumentation-asgi: instrumentation/opentelemetry-instrumentation-asgi/tests
- test-instrumentation-asyncpg: instrumentation/opentelemetry-instrumentation-asyncpg/tests
- test-instrumentation-boto: instrumentation/opentelemetry-instrumentation-boto/tests
- test-instrumentation-botocore: instrumentation/opentelemetry-instrumentation-botocore/tests
- test-instrumentation-celery: instrumentation/opentelemetry-instrumentation-celery/tests
- test-instrumentation-dbapi: instrumentation/opentelemetry-instrumentation-dbapi/tests
- test-instrumentation-django: instrumentation/opentelemetry-instrumentation-django/tests
- test-instrumentation-example-app: docs/examples/opentelemetry-example-app/tests
- test-instrumentation-elasticsearch{2,5,6,7}: instrumentation/opentelemetry-instrumentation-elasticsearch/tests
- test-instrumentation-falcon: instrumentation/opentelemetry-instrumentation-falcon/tests
- test-instrumentation-fastapi: instrumentation/opentelemetry-instrumentation-fastapi/tests
- test-instrumentation-flask: instrumentation/opentelemetry-instrumentation-flask/tests
- test-instrumentation-grpc: instrumentation/opentelemetry-instrumentation-grpc/tests
- test-instrumentation-jinja2: instrumentation/opentelemetry-instrumentation-jinja2/tests
- test-instrumentation-mysql: instrumentation/opentelemetry-instrumentation-mysql/tests
- test-instrumentation-psycopg2: instrumentation/opentelemetry-instrumentation-psycopg2/tests
- test-instrumentation-pymemcache: instrumentation/opentelemetry-instrumentation-pymemcache/tests
- test-instrumentation-pymongo: instrumentation/opentelemetry-instrumentation-pymongo/tests
- test-instrumentation-pymysql: instrumentation/opentelemetry-instrumentation-pymysql/tests
- test-instrumentation-pyramid: instrumentation/opentelemetry-instrumentation-pyramid/tests
- test-instrumentation-redis: instrumentation/opentelemetry-instrumentation-redis/tests
- test-instrumentation-requests: instrumentation/opentelemetry-instrumentation-requests/tests
- test-instrumentation-sqlalchemy: instrumentation/opentelemetry-instrumentation-sqlalchemy/tests
- test-instrumentation-sqlite3: instrumentation/opentelemetry-instrumentation-sqlite3/tests
- test-instrumentation-starlette: instrumentation/opentelemetry-instrumentation-starlette/tests
- test-instrumentation-system-metrics: instrumentation/opentelemetry-instrumentation-system-metrics/tests
- test-instrumentation-tornado: instrumentation/opentelemetry-instrumentation-tornado/tests
- test-instrumentation-wsgi: instrumentation/opentelemetry-instrumentation-wsgi/tests
test-exporter-jaeger: exporter/opentelemetry-exporter-jaeger/tests
- test-exporter-datadog: exporter/opentelemetry-exporter-datadog/tests
test-exporter-opencensus: exporter/opentelemetry-exporter-opencensus/tests
test-exporter-otlp: exporter/opentelemetry-exporter-otlp/tests
test-exporter-prometheus: exporter/opentelemetry-exporter-prometheus/tests
@@ -254,35 +91,9 @@ commands_pre =
test-core-proto: pip install {toxinidir}/opentelemetry-proto
instrumentation: pip install {toxinidir}/opentelemetry-instrumentation
- example-app: pip install {toxinidir}/opentelemetry-instrumentation {toxinidir}/instrumentation/opentelemetry-instrumentation-requests {toxinidir}/instrumentation/opentelemetry-instrumentation-wsgi {toxinidir}/instrumentation/opentelemetry-instrumentation-flask {toxinidir}/docs/examples/opentelemetry-example-app
-
- getting-started: pip install -e {toxinidir}/opentelemetry-instrumentation -e {toxinidir}/instrumentation/opentelemetry-instrumentation-requests -e {toxinidir}/instrumentation/opentelemetry-instrumentation-wsgi -e {toxinidir}/instrumentation/opentelemetry-instrumentation-flask
-
- celery: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-celery[test]
+ example-app: pip install {toxinidir}/opentelemetry-instrumentation {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-requests {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-wsgi {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-flask {toxinidir}/docs/examples/opentelemetry-example-app
- grpc: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-grpc[test]
-
- wsgi,falcon,flask,django,pyramid: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-wsgi
- asgi,starlette,fastapi: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-asgi
-
- asyncpg: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-asyncpg
-
- boto: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-botocore[test]
- boto: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-boto[test]
-
- falcon: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-falcon[test]
-
- flask: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-flask[test]
-
- botocore: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-botocore[test]
-
- dbapi: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi[test]
-
- django: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-django[test]
-
- fastapi: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-fastapi[test]
-
- mysql: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi {toxinidir}/instrumentation/opentelemetry-instrumentation-mysql[test]
+ getting-started: pip install -e {toxinidir}/opentelemetry-instrumentation -e {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-requests -e {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-wsgi -e {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-flask
opencensus: pip install {toxinidir}/exporter/opentelemetry-exporter-opencensus
@@ -291,47 +102,10 @@ commands_pre =
prometheus: pip install {toxinidir}/exporter/opentelemetry-exporter-prometheus
- pymemcache: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymemcache[test]
-
- pymongo: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymongo[test]
-
- psycopg2: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi {toxinidir}/instrumentation/opentelemetry-instrumentation-psycopg2[test]
-
- pymysql: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi {toxinidir}/instrumentation/opentelemetry-instrumentation-pymysql[test]
-
- pyramid: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pyramid[test]
-
- sqlite3: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi {toxinidir}/instrumentation/opentelemetry-instrumentation-sqlite3[test]
-
- redis: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-redis[test]
-
- requests: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-requests[test]
-
- starlette: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-starlette[test]
-
- tornado: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-tornado
-
- jinja2: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-jinja2[test]
-
- aiohttp-client: pip install {toxinidir}/opentelemetry-sdk {toxinidir}/instrumentation/opentelemetry-instrumentation-aiohttp-client
-
- aiopg: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-aiopg[test]
-
jaeger: pip install {toxinidir}/exporter/opentelemetry-exporter-jaeger
- opentracing-shim: pip install {toxinidir}/opentelemetry-sdk
- opentracing-shim: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-opentracing-shim
-
- datadog: pip install {toxinidir}/opentelemetry-sdk {toxinidir}/exporter/opentelemetry-exporter-datadog
-
zipkin: pip install {toxinidir}/exporter/opentelemetry-exporter-zipkin
- sqlalchemy: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-sqlalchemy
-
- system-metrics: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-system-metrics[test]
-
- elasticsearch{2,5,6,7}: pip install {toxinidir}/opentelemetry-instrumentation {toxinidir}/instrumentation/opentelemetry-instrumentation-elasticsearch[test]
-
; In order to get a healthy coverage report,
; we have to install packages in editable mode.
coverage: python {toxinidir}/scripts/eachdist.py install --editable
@@ -398,9 +172,8 @@ commands_pre =
pip install -e {toxinidir}/opentelemetry-api \
-e {toxinidir}/opentelemetry-sdk \
-e {toxinidir}/opentelemetry-instrumentation \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-requests \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-wsgi \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-flask
+ -e {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-requests \
+ -e {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-wsgi
commands =
{toxinidir}/scripts/tracecontext-integration-test.sh
@@ -408,41 +181,12 @@ commands =
[testenv:docker-tests]
deps =
pytest
- asyncpg==0.20.1
- docker-compose >= 1.25.2
- mysql-connector-python ~= 8.0
- pymongo ~= 3.1
- pymysql ~= 0.9.3
- psycopg2-binary ~= 2.8.4
- aiopg >= 0.13.0
- sqlalchemy ~= 1.3.16
- redis ~= 3.3.11
- celery ~= 4.0, != 4.4.4
changedir =
tests/opentelemetry-docker-tests/tests
commands_pre =
- pip install -e {toxinidir}/opentelemetry-api \
- -e {toxinidir}/opentelemetry-sdk \
- -e {toxinidir}/opentelemetry-instrumentation \
- -e {toxinidir}/tests/util \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-asyncpg \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-celery \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-mysql \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-psycopg2 \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-pymongo \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-pymysql \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-sqlalchemy \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-aiopg \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-redis \
- -e {toxinidir}/instrumentation/opentelemetry-instrumentation-system-metrics \
- -e {toxinidir}/exporter/opentelemetry-exporter-opencensus
- docker-compose up -d
- python check_availability.py
+ pip install -e {toxinidir}/exporter/opentelemetry-exporter-opencensus
commands =
pytest {posargs}
-commands_post =
- docker-compose down -v