Skip to content

test removing thread specific logic. upgrade to sqlalchemy ~1.4 #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
57e182a
test removing thread specific logic. upgrade to sqlalchemy ~1.4
mnbbrown Jul 6, 2021
8d58c2b
wip
mnbbrown Jul 6, 2021
51c53ff
add _span to sqlalchemy execution context instead of maintaining mapping
mnbbrown Jul 6, 2021
3d4087c
account for add_all optimisations in sqlalchemy 1.4
mnbbrown Jul 6, 2021
4a723bb
update docstring
mnbbrown Jul 6, 2021
5ade34e
add tests for async. fix black issues
mnbbrown Jul 7, 2021
ee58049
lint fixes
mnbbrown Jul 7, 2021
c034e9f
run tox -e generate
mnbbrown Jul 7, 2021
0eabf8e
use pytest mark to skip tests. fix work directory for sqlalchemy tests
mnbbrown Jul 7, 2021
83937c0
fix lint issues
mnbbrown Jul 7, 2021
9164d9d
address pylint
mnbbrown Jul 7, 2021
b51e4f1
fix linter issues + generate
mnbbrown Jul 7, 2021
07b2f2b
remove IsolatedAsyncioTestCase as not supported in python < 3.8
mnbbrown Jul 7, 2021
f1985f6
update CHANGELOG
mnbbrown Jul 7, 2021
ae8ce9b
address PR comments
mnbbrown Jul 8, 2021
3a7c84d
add comment about execute_values for psycopg2 dialect
mnbbrown Jul 10, 2021
5e38f5a
use SQLAlchemy 1.1 for tests
mnbbrown Jul 14, 2021
83e0e4f
remove gen file
mnbbrown Jul 24, 2021
125de32
use packaging to test versions
mnbbrown Jul 24, 2021
c5c6977
Add hooks for aiohttp, asgi, starlette, fastAPI, urllib, urllib3 (#576)
Jul 26, 2021
a04fb0e
Back to develop after 0.23b0 release (#606)
srikanthccv Jul 27, 2021
14b0a3f
Provide excluded_urls argument to Flask instrumentation (#604)
mattoberle Jul 29, 2021
daadcec
Merge branch 'main' into sqlalchemy-14
mnbbrown Jul 30, 2021
d671a10
SDK extension does not need to depend on API directly (#605)
NathanielRN Aug 2, 2021
62cbe6d
Merge branch 'main' into sqlalchemy-14
srikanthccv Aug 3, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
- 'release/*'
pull_request:
env:
CORE_REPO_SHA: 67bbad45917baa354a3a6d0d4361da48ff13fd31
CORE_REPO_SHA: 1c8449dee58b702b2505e2aefeb3c4106d1e33cf

jobs:
build:
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.4.0-0.23b0...HEAD)

### Added
- `opentelemetry-sdk-extension-aws` Add AWS resource detectors to extension package
([#586](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/586))
- `opentelemetry-instrumentation-asgi`, `opentelemetry-instrumentation-aiohttp-client`, `openetelemetry-instrumentation-fastapi`,
`opentelemetry-instrumentation-starlette`, `opentelemetry-instrumentation-urllib`, `opentelemetry-instrumentation-urllib3` Added `request_hook` and `response_hook` callbacks
([#576](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/576))

### Changed
- Enable explicit `excluded_urls` argument in `opentelemetry-instrumentation-flask`
([#604](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/604))

## [1.4.0-0.23b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.4.0-0.23b0) - 2021-07-21

Expand Down Expand Up @@ -57,6 +66,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#563](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/563))
- `opentelemetry-exporter-datadog` Datadog exporter should not use `unknown_service` as fallback resource service name.
([#570](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/570))
- Add support for the async extension of SQLAlchemy (>= 1.4)
([#568](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/568))

### Added
- `opentelemetry-instrumentation-httpx` Add `httpx` instrumentation
Expand Down
2 changes: 1 addition & 1 deletion _template/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.

__version__ = "0.23b0"
__version__ = "0.24.dev0"
2 changes: 1 addition & 1 deletion eachdist.ini
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ packages=
opentelemetry-api

[prerelease]
version=0.23b0
version=0.24.dev0

packages=
all
Expand Down
2 changes: 1 addition & 1 deletion exporter/opentelemetry-exporter-datadog/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ install_requires =
ddtrace>=0.34.0,<0.47.0
opentelemetry-api ~= 1.3
opentelemetry-sdk ~= 1.3
opentelemetry-semantic-conventions == 0.23b0
opentelemetry-semantic-conventions == 0.24.dev0

[options.packages.find]
where = src
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.

__version__ = "0.23b0"
__version__ = "0.24.dev0"
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ package_dir=
packages=find_namespace:
install_requires =
opentelemetry-api ~= 1.3
opentelemetry-semantic-conventions == 0.23b0
opentelemetry-instrumentation == 0.23b0
opentelemetry-util-http == 0.23b0
opentelemetry-semantic-conventions == 0.24.dev0
opentelemetry-instrumentation == 0.24.dev0
opentelemetry-util-http == 0.24.dev0
wrapt >= 1.0.0, < 2.0.0

[options.packages.find]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,25 @@ def strip_query_params(url: yarl.URL) -> str:
)
from opentelemetry.propagate import inject
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.trace import SpanKind, TracerProvider, get_tracer
from opentelemetry.trace import Span, SpanKind, TracerProvider, get_tracer
from opentelemetry.trace.status import Status, StatusCode
from opentelemetry.util.http import remove_url_credentials

_UrlFilterT = typing.Optional[typing.Callable[[str], str]]
_SpanNameT = typing.Optional[
typing.Union[typing.Callable[[aiohttp.TraceRequestStartParams], str], str]
_RequestHookT = typing.Optional[
typing.Callable[[Span, aiohttp.TraceRequestStartParams], None]
]
_ResponseHookT = typing.Optional[
typing.Callable[
[
Span,
typing.Union[
aiohttp.TraceRequestEndParams,
aiohttp.TraceRequestExceptionParams,
],
],
None,
]
]


Expand All @@ -108,7 +120,8 @@ def url_path_span_name(params: aiohttp.TraceRequestStartParams) -> str:

def create_trace_config(
url_filter: _UrlFilterT = None,
span_name: _SpanNameT = None,
request_hook: _RequestHookT = None,
response_hook: _ResponseHookT = None,
tracer_provider: TracerProvider = None,
) -> aiohttp.TraceConfig:
"""Create an aiohttp-compatible trace configuration.
Expand All @@ -134,15 +147,16 @@ def create_trace_config(
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 Callable request_hook: Optional callback that can modify span name and request params.
:param Callable response_hook: Optional callback that can modify span name and response params.
: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
# which doesn't exist in the aiohttp intersphinx inventory.
# Explicitly specify the type for the `request_hook` and `response_hook` param and rtype to work
# around this issue.

tracer = get_tracer(__name__, __version__, tracer_provider)
Expand All @@ -161,17 +175,15 @@ async def on_request_start(
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)
request_span_name = "HTTP {}".format(http_method)

trace_config_ctx.span = trace_config_ctx.tracer.start_span(
request_span_name, kind=SpanKind.CLIENT,
)

if callable(request_hook):
request_hook(trace_config_ctx.span, params)

if trace_config_ctx.span.is_recording():
attributes = {
SpanAttributes.HTTP_METHOD: http_method,
Expand All @@ -198,6 +210,9 @@ async def on_request_end(
if trace_config_ctx.span is None:
return

if callable(response_hook):
response_hook(trace_config_ctx.span, params)

if trace_config_ctx.span.is_recording():
trace_config_ctx.span.set_status(
Status(http_status_to_status_code(int(params.response.status)))
Expand All @@ -215,6 +230,9 @@ async def on_request_exception(
if trace_config_ctx.span is None:
return

if callable(response_hook):
response_hook(trace_config_ctx.span, params)

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)
Expand All @@ -223,7 +241,7 @@ async def on_request_exception(
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
tracer=tracer, url_filter=url_filter, **kwargs
)

trace_config = aiohttp.TraceConfig(
Expand All @@ -240,7 +258,8 @@ def _trace_config_ctx_factory(**kwargs):
def _instrument(
tracer_provider: TracerProvider = None,
url_filter: _UrlFilterT = None,
span_name: _SpanNameT = None,
request_hook: _RequestHookT = None,
response_hook: _ResponseHookT = None,
):
"""Enables tracing of all ClientSessions

Expand All @@ -256,7 +275,8 @@ def instrumented_init(wrapped, instance, args, kwargs):

trace_config = create_trace_config(
url_filter=url_filter,
span_name=span_name,
request_hook=request_hook,
response_hook=response_hook,
tracer_provider=tracer_provider,
)
trace_config._is_instrumented_by_opentelemetry = True
Expand Down Expand Up @@ -304,12 +324,14 @@ def _instrument(self, **kwargs):
``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.
``request_hook``: An optional callback that is invoked right after a span is created.
``response_hook``: An optional callback which is invoked right before the span is finished processing a response.
"""
_instrument(
tracer_provider=kwargs.get("tracer_provider"),
url_filter=kwargs.get("url_filter"),
span_name=kwargs.get("span_name"),
request_hook=kwargs.get("request_hook"),
response_hook=kwargs.get("response_hook"),
)

def _uninstrument(self, **kwargs):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.

__version__ = "0.23b0"
__version__ = "0.24.dev0"
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.test.test_base import TestBase
from opentelemetry.trace import StatusCode
from opentelemetry.trace import Span, StatusCode


def run_with_test_server(
Expand Down Expand Up @@ -161,46 +161,51 @@ def test_not_recording(self):
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",
),
def test_hooks(self):
method = "PATCH"
path = "/some/path"
expected = "PATCH - /some/path"

def request_hook(span: Span, params: aiohttp.TraceRequestStartParams):
span.update_name("{} - {}".format(params.method, params.url.path))

def response_hook(
span: Span,
params: typing.Union[
aiohttp.TraceRequestEndParams,
aiohttp.TraceRequestExceptionParams,
],
):
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,
)
span.set_attribute("response_hook_attr", "value")

self.assert_spans(
[
(
expected,
(StatusCode.UNSET, None),
{
SpanAttributes.HTTP_METHOD: method,
SpanAttributes.HTTP_URL: "http://{}:{}{}".format(
host, port, path
),
SpanAttributes.HTTP_STATUS_CODE: int(
HTTPStatus.OK
),
},
)
]
)
self.memory_exporter.clear()
host, port = self._http_request(
trace_config=aiohttp_client.create_trace_config(
request_hook=request_hook, response_hook=response_hook,
),
method=method,
url=path,
status_code=HTTPStatus.OK,
)

for span in self.memory_exporter.get_finished_spans():
self.assertEqual(span.name, expected)
self.assertEqual(
(span.status.status_code, span.status.description),
(StatusCode.UNSET, None),
)
self.assertEqual(
span.attributes[SpanAttributes.HTTP_METHOD], method
)
self.assertEqual(
span.attributes[SpanAttributes.HTTP_URL],
"http://{}:{}{}".format(host, port, path),
)
self.assertEqual(
span.attributes[SpanAttributes.HTTP_STATUS_CODE], HTTPStatus.OK
)
self.assertIn("response_hook_attr", span.attributes)
self.assertEqual(span.attributes["response_hook_attr"], "value")
self.memory_exporter.clear()

def test_url_filter_option(self):
# Strips all query params from URL before adding as a span attribute.
Expand Down Expand Up @@ -501,19 +506,32 @@ def strip_query_params(url: yarl.URL) -> str:
span.attributes[SpanAttributes.HTTP_URL],
)

def test_span_name(self):
def span_name_callback(params: aiohttp.TraceRequestStartParams) -> str:
return "{} - {}".format(params.method, params.url.path)
def test_hooks(self):
def request_hook(span: Span, params: aiohttp.TraceRequestStartParams):
span.update_name("{} - {}".format(params.method, params.url.path))

def response_hook(
span: Span,
params: typing.Union[
aiohttp.TraceRequestEndParams,
aiohttp.TraceRequestExceptionParams,
],
):
span.set_attribute("response_hook_attr", "value")

AioHttpClientInstrumentor().uninstrument()
AioHttpClientInstrumentor().instrument(span_name=span_name_callback)
AioHttpClientInstrumentor().instrument(
request_hook=request_hook, response_hook=response_hook
)

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)
self.assertIn("response_hook_attr", span.attributes)
self.assertEqual(span.attributes["response_hook_attr"], "value")


class TestLoadingAioHttpInstrumentor(unittest.TestCase):
Expand Down
8 changes: 4 additions & 4 deletions instrumentation/opentelemetry-instrumentation-aiopg/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ package_dir=
packages=find_namespace:
install_requires =
opentelemetry-api ~= 1.3
opentelemetry-semantic-conventions == 0.23b0
opentelemetry-instrumentation-dbapi == 0.23b0
opentelemetry-instrumentation == 0.23b0
opentelemetry-semantic-conventions == 0.24.dev0
opentelemetry-instrumentation-dbapi == 0.24.dev0
opentelemetry-instrumentation == 0.24.dev0
wrapt >= 1.0.0, < 2.0.0

[options.extras_require]
test =
opentelemetry-test == 0.23b0
opentelemetry-test == 0.24.dev0

[options.packages.find]
where = src
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.

__version__ = "0.23b0"
__version__ = "0.24.dev0"
Loading