Skip to content

Commit

Permalink
Remove usage of pkg_resources (#3047)
Browse files Browse the repository at this point in the history
* Remove usage of pkg_resources

Fixes #2927

* WIP

* WIP

* Add test case for _load_providers

* Fix test case for 3.9

* Fix lint

* Fix 3.7 sdk tests

* Fix lint

* Fix lint

* Fix mypy again

* WIP

* WIP

* WIP

* WIP

* Move to module

* Fix SDK

* Fix mypy

* Refactor load call

* Fix mypy

* Fix lint

* Fix opencensus exporter

* Refactor implementation

* Add missing dependency

* Undo changes in shim

* Fix dependency

* Revert "Undo changes in shim"

This reverts commit bd82b8f.

* Update dependencies

* Update dependency for opencensus exporter

* Add descriptive error
  • Loading branch information
ocelotl authored Feb 1, 2023
1 parent 1d25153 commit 2e14fe1
Show file tree
Hide file tree
Showing 43 changed files with 637 additions and 181 deletions.
4 changes: 2 additions & 2 deletions exporter/opentelemetry-exporter-opencensus/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ classifiers = [
dependencies = [
"grpcio >= 1.0.0, < 2.0.0",
"opencensus-proto >= 0.1.0, < 1.0.0",
"opentelemetry-api ~= 1.3",
"opentelemetry-sdk ~= 1.3",
"opentelemetry-api >= 1.16.0.dev",
"opentelemetry-sdk >= 1.15",
"protobuf ~= 3.13",
"setuptools >= 16.0",
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import socket
import time
from os import getpid
from socket import gethostname
from time import time

import pkg_resources
# pylint: disable=wrong-import-position
from google.protobuf.timestamp_pb2 import Timestamp
from opencensus.proto.agent.common.v1 import common_pb2
from opencensus.proto.trace.v1 import trace_pb2
Expand All @@ -25,10 +25,9 @@
__version__ as opencensusexporter_exporter_version,
)
from opentelemetry.trace import SpanKind
from opentelemetry.util._importlib_metadata import version

OPENTELEMETRY_VERSION = pkg_resources.get_distribution(
"opentelemetry-api"
).version
OPENTELEMETRY_VERSION = version("opentelemetry-api")


def proto_timestamp_from_time_ns(time_ns):
Expand Down Expand Up @@ -88,11 +87,9 @@ def get_node(service_name, host_name):
"""
return common_pb2.Node(
identifier=common_pb2.ProcessIdentifier(
host_name=socket.gethostname() if host_name is None else host_name,
pid=os.getpid(),
start_timestamp=proto_timestamp_from_time_ns(
int(time.time() * 1e9)
),
host_name=gethostname() if host_name is None else host_name,
pid=getpid(),
start_timestamp=proto_timestamp_from_time_ns(int(time() * 1e9)),
),
library_info=common_pb2.LibraryInfo(
language=common_pb2.LibraryInfo.Language.Value("PYTHON"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
)
from opentelemetry.trace import TraceFlags, format_span_id, format_trace_id

from .common_tests import TEST_SERVICE_NAME, CommonEncoderTestCases
from .common_tests import ( # pylint: disable=import-error
TEST_SERVICE_NAME,
CommonEncoderTestCases,
)


# pylint: disable=protected-access
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
)
from opentelemetry.trace import SpanKind, TraceFlags

from .common_tests import TEST_SERVICE_NAME, CommonEncoderTestCases
from .common_tests import ( # pylint: disable=import-error
TEST_SERVICE_NAME,
CommonEncoderTestCases,
)


# pylint: disable=protected-access
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
)
from opentelemetry.trace import SpanKind

from .common_tests import TEST_SERVICE_NAME, CommonEncoderTestCases
from .common_tests import ( # pylint: disable=import-error
TEST_SERVICE_NAME,
CommonEncoderTestCases,
)


# pylint: disable=protected-access
Expand Down
1 change: 1 addition & 0 deletions opentelemetry-api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ classifiers = [
dependencies = [
"Deprecated >= 1.2.6",
"setuptools >= 16.0",
"importlib-metadata >= 5.0.0; python_version=='3.7'"
]
dynamic = [
"version",
Expand Down
26 changes: 16 additions & 10 deletions opentelemetry-api/src/opentelemetry/context/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
from os import environ
from uuid import uuid4

from pkg_resources import iter_entry_points

from opentelemetry.context.context import Context, _RuntimeContext
# pylint: disable=wrong-import-position
from opentelemetry.context.context import Context, _RuntimeContext # noqa
from opentelemetry.environment_variables import OTEL_PYTHON_CONTEXT
from opentelemetry.util._importlib_metadata import entry_points

logger = logging.getLogger(__name__)
_RUNTIME_CONTEXT = None # type: typing.Optional[_RuntimeContext]
Expand All @@ -41,27 +41,33 @@ def _load_runtime_context(func: _F) -> _F:
@wraps(func) # type: ignore[misc]
def wrapper( # type: ignore[misc]
*args: typing.Tuple[typing.Any, typing.Any],
**kwargs: typing.Dict[typing.Any, typing.Any]
**kwargs: typing.Dict[typing.Any, typing.Any],
) -> typing.Optional[typing.Any]:
global _RUNTIME_CONTEXT # pylint: disable=global-statement

with _RUNTIME_CONTEXT_LOCK:
if _RUNTIME_CONTEXT is None:
# FIXME use a better implementation of a configuration manager to avoid having
# to get configuration values straight from environment variables
# FIXME use a better implementation of a configuration manager
# to avoid having to get configuration values straight from
# environment variables
default_context = "contextvars_context"

configured_context = environ.get(
OTEL_PYTHON_CONTEXT, default_context
) # type: str
try:
_RUNTIME_CONTEXT = next(
iter_entry_points(
"opentelemetry_context", configured_context

_RUNTIME_CONTEXT = next( # type: ignore
iter( # type: ignore
entry_points( # type: ignore
group="opentelemetry_context",
name=configured_context,
)
)
).load()()

except Exception: # pylint: disable=broad-except
logger.error(
logger.exception(
"Failed to load context: %s", configured_context
)
return func(*args, **kwargs) # type: ignore[misc]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def get_meter(
version: Optional. The version string of the
instrumenting library. Usually this should be the same as
``pkg_resources.get_distribution(instrumenting_library_name).version``.
``importlib.metadata.version(instrumenting_library_name)``.
schema_url: Optional. Specifies the Schema URL of the emitted telemetry.
"""
Expand Down
23 changes: 16 additions & 7 deletions opentelemetry-api/src/opentelemetry/propagate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,21 @@ def example_route():
https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md
"""

import typing
from logging import getLogger
from os import environ

from pkg_resources import iter_entry_points
from typing import Optional

from opentelemetry.context.context import Context
from opentelemetry.environment_variables import OTEL_PROPAGATORS
from opentelemetry.propagators import composite, textmap
from opentelemetry.util._importlib_metadata import entry_points

logger = getLogger(__name__)


def extract(
carrier: textmap.CarrierT,
context: typing.Optional[Context] = None,
context: Optional[Context] = None,
getter: textmap.Getter[textmap.CarrierT] = textmap.default_getter,
) -> Context:
"""Uses the configured propagator to extract a Context from the carrier.
Expand All @@ -104,7 +103,7 @@ def extract(

def inject(
carrier: textmap.CarrierT,
context: typing.Optional[Context] = None,
context: Optional[Context] = None,
setter: textmap.Setter[textmap.CarrierT] = textmap.default_setter,
) -> None:
"""Uses the configured propagator to inject a Context into the carrier.
Expand All @@ -129,20 +128,30 @@ def inject(
"tracecontext,baggage",
)


for propagator in environ_propagators.split(","):
propagator = propagator.strip()

try:

propagators.append( # type: ignore
next( # type: ignore
iter_entry_points("opentelemetry_propagator", propagator)
iter( # type: ignore
entry_points( # type: ignore
group="opentelemetry_propagator",
name=propagator,
)
)
).load()()
)

except Exception: # pylint: disable=broad-except
logger.exception(
"Failed to load configured propagator `%s`", propagator
"Failed to load configured propagator: %s", propagator
)
raise


_HTTP_TEXT_FORMAT = composite.CompositePropagator(propagators) # type: ignore


Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-api/src/opentelemetry/trace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def get_tracer(
instrumenting_library_version: Optional. The version string of the
instrumenting library. Usually this should be the same as
``pkg_resources.get_distribution(instrumenting_library_name).version``.
``importlib.metadata.version(instrumenting_library_name)``.
schema_url: Optional. Specifies the Schema URL of the emitted telemetry.
"""
Expand Down
38 changes: 38 additions & 0 deletions opentelemetry-api/src/opentelemetry/util/_importlib_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 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 version_info

# FIXME remove this when support for 3.7 is dropped.
if version_info.minor == 7:
# pylint: disable=import-error
from importlib_metadata import entry_points, version # type: ignore

# FIXME remove this file when support for 3.9 is dropped.
elif version_info.minor in (8, 9):
# pylint: disable=import-error
from importlib.metadata import (
entry_points as importlib_metadata_entry_points,
)
from importlib.metadata import version

def entry_points(group: str, name: str): # type: ignore
for entry_point in importlib_metadata_entry_points()[group]:
if entry_point.name == name:
yield entry_point

else:
from importlib.metadata import entry_points, version

__all__ = ["entry_points", "version"]
30 changes: 16 additions & 14 deletions opentelemetry-api/src/opentelemetry/util/_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from os import environ
from typing import TYPE_CHECKING, TypeVar, cast

from pkg_resources import iter_entry_points
from opentelemetry.util._importlib_metadata import entry_points

if TYPE_CHECKING:
from opentelemetry.metrics import MeterProvider
Expand All @@ -30,23 +30,25 @@
def _load_provider(
provider_environment_variable: str, provider: str
) -> Provider:

try:
entry_point = next(
iter_entry_points(
f"opentelemetry_{provider}",
name=cast(
str,
environ.get(
provider_environment_variable,
f"default_{provider}",
),
),
)

provider_name = cast(
str,
environ.get(provider_environment_variable, f"default_{provider}"),
)

return cast(
Provider,
entry_point.load()(),
next( # type: ignore
iter( # type: ignore
entry_points( # type: ignore
group=f"opentelemetry_{provider}",
name=provider_name,
)
)
).load()(),
)
except Exception: # pylint: disable=broad-except
logger.error("Failed to load configured provider %s", provider)
logger.exception("Failed to load configured provider %s", provider)
raise
9 changes: 0 additions & 9 deletions opentelemetry-api/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,3 @@
# 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 pkg_resources

# naming the tests module as a namespace package ensures that
# relative imports will resolve properly for other test packages,
# as it enables searching for a composite of multiple test modules.
#
# only the opentelemetry-api directory needs this code, as it is
# the first tests module found by pylint during eachdist.py lint
pkg_resources.declare_namespace(__name__)
Loading

0 comments on commit 2e14fe1

Please sign in to comment.