-
Notifications
You must be signed in to change notification settings - Fork 652
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
498 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
__pycache__ | ||
*.egg | ||
*.egg-info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
README | ||
====== | ||
|
||
Overview | ||
-------- | ||
|
||
This is a prototype to implement `error handling`_ in Python. | ||
|
||
The user only calls API functions or methods, never SDK functions or methods. | ||
|
||
Every SDK must implement every public function or method defined in the API | ||
except for the SDK setting function. | ||
|
||
A safety mechanism is applied to every API function or method (except for the | ||
SDK setting function or method) and only to every API function or method. | ||
|
||
This safety mechanism has 3 main components: | ||
|
||
1. A predefined value to be returned in case of an exception being raised. This | ||
value is predefined and independently set for every function or method. | ||
2. A `try` / `except` block that catches any exception raised when executing | ||
the function or method code. | ||
3. A Python `warning`_ that is "raised" if an exception is raised in the code | ||
protected by the safety mechanism. | ||
|
||
The API provides a function to set a specific SDK. This function is | ||
intentionally not protected by the safety mechanism mentioned above because the | ||
specification `mentions`_ this: | ||
|
||
The API or SDK may fail fast and cause the application to fail on | ||
initialization... | ||
|
||
*Initialization* is understood as the process of setting the SDK. | ||
|
||
When an API function or method is called without an SDK being set, a warning | ||
will be raised and the predefined value of `None` will be returned. | ||
|
||
After an SDK is set, calling an API function or method will call its | ||
corresponding SDJ function or method. Any exception raised by the SDK function | ||
or method will be caught by the safety mechanism and the predefined value | ||
returned instead. | ||
|
||
The Python warning that is "raised" when an exception is raised in the SDK | ||
function or method can be transformed into a full exception by running the | ||
Python interpreter with the `-W error` option. This Python feature is used to | ||
satisfy this `specification requirement`_. | ||
|
||
How to run | ||
---------- | ||
|
||
0. Create a virtual environment and activate it | ||
1. Run ``pip install -e opentelemetry-api`` | ||
2. Run ``pip install -e opentelemetry-sdk`` | ||
3. Run ``python application.py`` | ||
4. Run ``python -W error application.py`` | ||
|
||
Noice how even failed operations (divisions by zero) don't crash the | ||
application in step 3, but they do in step 4. | ||
|
||
|
||
.. _error handling: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/error-handling.md | ||
.. _warning: https://docs.python.org/3/library/warnings.html | ||
.. _specification requirement: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/error-handling.md#configuring-error-handlers | ||
.. _mentions: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/error-handling.md#basic-error-handling-principles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Only API objects are imported because the user only calls API functions or | ||
# methods. | ||
from opentelemetry.configuration import set_sdk | ||
from opentelemetry.trace import function, Class0 | ||
|
||
# This is the function that sets the SDK. After this is set, any call to an API | ||
# function or method will end up calling its corresponding SDK function or | ||
# method. | ||
set_sdk("sdk") | ||
|
||
# function returns the result of dividing its first argument by its second | ||
# argument. | ||
|
||
# This does not raise an exception, the resulting value of 2.0 is returned. | ||
print(function(4, 2)) | ||
|
||
# This is a division by zero, it raises an exception, the safety mechanism | ||
# catches it and returns the predefined value of 0.0. | ||
print(function(1, 0)) | ||
|
||
|
||
# The class argument is stored in the SDK instance and method uses it to | ||
# multiply the result of the division of it first argument by the second before | ||
# returning the resulting value. | ||
class0 = Class0(2) | ||
|
||
# Class0.method returns the result of dividing its first argument by its second | ||
# argument. | ||
|
||
# This does not raise an exception, the resulting value of 4.0 is returned. | ||
print(class0.method(4, 2)) | ||
|
||
# This is a division by zero, it raises an exception, the safety mechanism | ||
# catches it and returns the predefined value of 0.0. | ||
print(class0.method(1, 0)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# 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-api | ||
description = OpenTelemetry Python API | ||
author = OpenTelemetry Authors | ||
author_email = [email protected] | ||
url = https://github.com/open-telemetry/opentelemetry-python/tree/main/opentelemetry-api | ||
platforms = any | ||
license = Apache-2.0 | ||
classifiers = | ||
Development Status :: 5 - Production/Stable | ||
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 | ||
Programming Language :: Python :: 3.9 | ||
Programming Language :: Python :: 3.10 | ||
Typing :: Typed | ||
|
||
[options] | ||
python_requires = >=3.6 | ||
package_dir= | ||
=src | ||
packages=find_namespace: | ||
zip_safe = False | ||
include_package_data = True | ||
|
||
[options.packages.find] | ||
where = src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# 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", "version.py") | ||
PACKAGE_INFO = {} | ||
with open(VERSION_FILENAME, encoding="utf-8") as f: | ||
exec(f.read(), PACKAGE_INFO) | ||
|
||
setuptools.setup( | ||
version=PACKAGE_INFO["__version__"], | ||
) |
50 changes: 50 additions & 0 deletions
50
safety_prototype/opentelemetry-api/src/opentelemetry/_safety.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# 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 functools import wraps | ||
from warnings import warn, resetwarnings | ||
from traceback import format_exception | ||
from sys import exc_info | ||
|
||
|
||
def _safe_function(predefined_return_value): | ||
""" | ||
This is the safety mechanism mentioned in the README file. | ||
This is used as a decorator on every function or method in the API. | ||
""" | ||
|
||
|
||
def internal(function): | ||
@wraps(function) | ||
def wrapper(*args, **kwargs): | ||
|
||
# This is the try / except block mentioned in the README file. | ||
try: | ||
exception = None | ||
return function(*args, **kwargs) | ||
except Exception: # pylint: disable=broad-except | ||
exception = "".join(format_exception(*exc_info())) | ||
|
||
if exception is not None: | ||
# This is the warning mentioned in the README file. | ||
warn(f"OpenTelemetry handled an exception:\n\n{exception}") | ||
exception = None | ||
resetwarnings() | ||
|
||
return predefined_return_value | ||
|
||
return wrapper | ||
|
||
return internal |
41 changes: 41 additions & 0 deletions
41
safety_prototype/opentelemetry-api/src/opentelemetry/configuration.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# 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 pkg_resources import iter_entry_points | ||
from importlib import import_module | ||
|
||
_sdk = None | ||
|
||
|
||
def set_sdk(sdk_name: str) -> None: | ||
""" | ||
This is the SDK setting function mentioned in the README file. | ||
It is intentionally not protected to make it possible for the application | ||
to fail fast if it was not possible to set the SDK. In an actual | ||
implementation of this prototype, the SDK setting mechanism may take | ||
different forms to take into consideration that this SDK setting process | ||
may happen also in auto instrumentation. This means that SDK setting may | ||
also happen by using environment variables or other form of configuration. | ||
""" | ||
global _sdk | ||
|
||
if _sdk is None: | ||
_sdk = next( | ||
iter_entry_points("opentelemetry_sdk", name=sdk_name) | ||
).load().__package__ | ||
|
||
|
||
def _get_sdk_module(path: str) -> object: | ||
return import_module(".".join([_sdk, path])) |
42 changes: 42 additions & 0 deletions
42
safety_prototype/opentelemetry-api/src/opentelemetry/trace/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# 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 an implementation of the API where every function or method is safe. | ||
Any call to a function or method defined here passes its arguments to a | ||
corresponding underlying SDK function or method. In this way, objects defined | ||
in this module act as proxies and (with the SDK setting function) are the only | ||
objects the user has contact with. | ||
""" | ||
|
||
from opentelemetry._safety import _safe_function | ||
from opentelemetry.configuration import _get_sdk_module | ||
from opentelemetry.trace.api import Class0 | ||
|
||
|
||
@_safe_function(0.0) | ||
def function(a: int, b: int) -> float: | ||
return _get_sdk_module("trace").function(a, b) | ||
|
||
|
||
class Class0(Class0): | ||
|
||
@_safe_function(None) | ||
def __init__(self, a: int) -> None: | ||
self._sdk_instance = _get_sdk_module("trace").Class0(a) | ||
|
||
@_safe_function(0.0) | ||
def method(self, a: int, b: int) -> float: | ||
return self._sdk_instance.method(a, b) |
44 changes: 44 additions & 0 deletions
44
safety_prototype/opentelemetry-api/src/opentelemetry/trace/api.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# 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 is the API. | ||
This module includes all functions and classes with their respective methods | ||
that an SDK must implement. SDKs must implement the contents of this module | ||
exactly, with the same names and signatures for functions and methods. This is | ||
necessary because the API proxy objects will call the SDK functions and methods | ||
in the exact same way as they are defined here. | ||
""" | ||
|
||
from abc import ABC, abstractmethod | ||
|
||
|
||
# There is no way to mandate the implementation of a function in a Python | ||
# module, so this is added to inform SDK implementations that this function is | ||
# to be implemented. A mechanism that checks SDK compliance can be implemented | ||
# as well and it can use the contents of this module to check SDKs. | ||
def function(a: int, b: int) -> float: | ||
pass | ||
|
||
|
||
class Class0(ABC): | ||
|
||
@abstractmethod | ||
def __init__(self, a: int) -> None: | ||
pass | ||
|
||
@abstractmethod | ||
def method(self, a: int, b: int) -> float: | ||
pass |
15 changes: 15 additions & 0 deletions
15
safety_prototype/opentelemetry-api/src/opentelemetry/version.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# 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__ = "1.6.2" |
Oops, something went wrong.