mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-28 12:43:39 +08:00
Add instrumentation for remoulade (#1082)
This commit is contained in:
10
.github/component_owners.yml
vendored
10
.github/component_owners.yml
vendored
@ -1,5 +1,9 @@
|
||||
components:
|
||||
|
||||
instrumentation/opentelemetry-instrumentation-boto3sqs:
|
||||
- oxeye-nikolay
|
||||
- nikosokolik
|
||||
|
||||
instrumentation/opentelemetry-instrumentation-kafka-python:
|
||||
- nozik
|
||||
|
||||
@ -7,9 +11,9 @@ components:
|
||||
- oxeye-nikolay
|
||||
- nikosokolik
|
||||
|
||||
instrumentation/opentelemetry-instrumentation-boto3sqs:
|
||||
- oxeye-nikolay
|
||||
- nikosokolik
|
||||
instrumentation/opentelemetry-instrumentation-remoulade:
|
||||
- ben-natan
|
||||
- machine424
|
||||
|
||||
propagator/opentelemetry-propagator-aws-xray:
|
||||
- NathanielRN
|
||||
|
@ -12,11 +12,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
([1109](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1109))
|
||||
- cleanup type hints for textmap `Getter` and `Setter` classes
|
||||
([1106](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1106))
|
||||
|
||||
### Added
|
||||
- `opentelemetry-instrumentation-remoulade` Initial release
|
||||
([#1082](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1082))
|
||||
|
||||
## [1.12.0rc1-0.31b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.12.0rc1-0.31b0) - 2022-05-17
|
||||
|
||||
|
||||
|
||||
### Fixed
|
||||
- `opentelemetry-instrumentation-aiohttp-client` make span attributes available to sampler
|
||||
([1072](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1072))
|
||||
|
@ -33,6 +33,7 @@ pymongo~=3.1
|
||||
PyMySQL~=0.9.3
|
||||
pyramid>=1.7
|
||||
redis>=2.6
|
||||
remoulade>=0.50
|
||||
sqlalchemy>=1.0
|
||||
tornado>=5.1.1
|
||||
ddtrace>=0.34.0
|
||||
|
@ -29,6 +29,7 @@
|
||||
| [opentelemetry-instrumentation-pymysql](./opentelemetry-instrumentation-pymysql) | PyMySQL < 2 |
|
||||
| [opentelemetry-instrumentation-pyramid](./opentelemetry-instrumentation-pyramid) | pyramid >= 1.7 |
|
||||
| [opentelemetry-instrumentation-redis](./opentelemetry-instrumentation-redis) | redis >= 2.6 |
|
||||
| [opentelemetry-instrumentation-remoulade](./opentelemetry-instrumentation-remoulade) | remoulade >= 0.50 |
|
||||
| [opentelemetry-instrumentation-requests](./opentelemetry-instrumentation-requests) | requests ~= 2.0 |
|
||||
| [opentelemetry-instrumentation-sklearn](./opentelemetry-instrumentation-sklearn) | scikit-learn ~= 0.24.0 |
|
||||
| [opentelemetry-instrumentation-sqlalchemy](./opentelemetry-instrumentation-sqlalchemy) | sqlalchemy |
|
||||
|
@ -0,0 +1,9 @@
|
||||
graft src
|
||||
graft tests
|
||||
global-exclude *.pyc
|
||||
global-exclude *.pyo
|
||||
global-exclude __pycache__/*
|
||||
include CHANGELOG.md
|
||||
include MANIFEST.in
|
||||
include README.rst
|
||||
include LICENSE
|
@ -0,0 +1,23 @@
|
||||
OpenTelemetry Remoulade Instrumentation
|
||||
=======================================
|
||||
|
||||
|pypi|
|
||||
|
||||
.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-remoulade.svg
|
||||
:target: https://pypi.org/project/opentelemetry-instrumentation-remoulade/
|
||||
|
||||
This library allows tracing requests made by the Remoulade library.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
::
|
||||
|
||||
pip install opentelemetry-instrumentation-remoulade
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
* `OpenTelemetry Remoulade Instrumentation <https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/remoulade/remoulade.html>`_
|
||||
* `OpenTelemetry Project <https://opentelemetry.io/>`_
|
||||
* `OpenTelemetry Python Examples <https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples>`_
|
@ -0,0 +1,56 @@
|
||||
# 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-remoulade
|
||||
description = OpenTelemetry Remoulade 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-contrib/tree/main/instrumentation/opentelemetry-instrumentation-remoulade
|
||||
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.7
|
||||
Programming Language :: Python :: 3.8
|
||||
Programming Language :: Python :: 3.9
|
||||
Programming Language :: Python :: 3.10
|
||||
|
||||
[options]
|
||||
python_requires = >=3.7
|
||||
package_dir=
|
||||
=src
|
||||
packages=find_namespace:
|
||||
install_requires =
|
||||
opentelemetry-api ~= 1.10
|
||||
opentelemetry-semantic-conventions == 0.31b0
|
||||
opentelemetry-instrumentation == 0.31b0
|
||||
|
||||
[options.extras_require]
|
||||
test =
|
||||
opentelemetry-test-utils == 0.31b0
|
||||
opentelemetry-sdk ~= 1.10
|
||||
|
||||
[options.packages.find]
|
||||
where = src
|
||||
|
||||
[options.entry_points]
|
||||
opentelemetry_instrumentor =
|
||||
remoulade = opentelemetry.instrumentation.remoulade:RemouladeInstrumentor
|
@ -0,0 +1,99 @@
|
||||
# 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.
|
||||
|
||||
|
||||
# DO NOT EDIT. THIS FILE WAS AUTOGENERATED FROM templates/instrumentation_setup.py.txt.
|
||||
# RUN `python scripts/generate_setup.py` TO REGENERATE.
|
||||
|
||||
|
||||
import distutils.cmd
|
||||
import json
|
||||
import os
|
||||
from configparser import ConfigParser
|
||||
|
||||
import setuptools
|
||||
|
||||
config = ConfigParser()
|
||||
config.read("setup.cfg")
|
||||
|
||||
# We provide extras_require parameter to setuptools.setup later which
|
||||
# overwrites the extras_require section from setup.cfg. To support extras_require
|
||||
# section in setup.cfg, we load it here and merge it with the extras_require param.
|
||||
extras_require = {}
|
||||
if "options.extras_require" in config:
|
||||
for key, value in config["options.extras_require"].items():
|
||||
extras_require[key] = [v for v in value.split("\n") if v.strip()]
|
||||
|
||||
BASE_DIR = os.path.dirname(__file__)
|
||||
PACKAGE_INFO = {}
|
||||
|
||||
VERSION_FILENAME = os.path.join(
|
||||
BASE_DIR,
|
||||
"src",
|
||||
"opentelemetry",
|
||||
"instrumentation",
|
||||
"remoulade",
|
||||
"version.py",
|
||||
)
|
||||
with open(VERSION_FILENAME, encoding="utf-8") as f:
|
||||
exec(f.read(), PACKAGE_INFO)
|
||||
|
||||
PACKAGE_FILENAME = os.path.join(
|
||||
BASE_DIR,
|
||||
"src",
|
||||
"opentelemetry",
|
||||
"instrumentation",
|
||||
"remoulade",
|
||||
"package.py",
|
||||
)
|
||||
with open(PACKAGE_FILENAME, encoding="utf-8") as f:
|
||||
exec(f.read(), PACKAGE_INFO)
|
||||
|
||||
# Mark any instruments/runtime dependencies as test dependencies as well.
|
||||
extras_require["instruments"] = PACKAGE_INFO["_instruments"]
|
||||
test_deps = extras_require.get("test", [])
|
||||
for dep in extras_require["instruments"]:
|
||||
test_deps.append(dep)
|
||||
|
||||
extras_require["test"] = test_deps
|
||||
|
||||
|
||||
class JSONMetadataCommand(distutils.cmd.Command):
|
||||
|
||||
description = (
|
||||
"print out package metadata as JSON. This is used by OpenTelemetry dev scripts to ",
|
||||
"auto-generate code in other places",
|
||||
)
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
metadata = {
|
||||
"name": config["metadata"]["name"],
|
||||
"version": PACKAGE_INFO["__version__"],
|
||||
"instruments": PACKAGE_INFO["_instruments"],
|
||||
}
|
||||
print(json.dumps(metadata))
|
||||
|
||||
|
||||
setuptools.setup(
|
||||
cmdclass={"meta": JSONMetadataCommand},
|
||||
version=PACKAGE_INFO["__version__"],
|
||||
extras_require=extras_require,
|
||||
)
|
@ -0,0 +1,185 @@
|
||||
# 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
|
||||
-----
|
||||
|
||||
* Start broker backend
|
||||
|
||||
::
|
||||
|
||||
docker run -p 5672:5672 rabbitmq
|
||||
|
||||
* Run instrumented actor
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from remoulade.brokers.rabbitmq import RabbitmqBroker
|
||||
import remoulade
|
||||
|
||||
RemouladeInstrumentor().instrument()
|
||||
|
||||
broker = RabbitmqBroker()
|
||||
remoulade.set_broker(broker)
|
||||
|
||||
@remoulade.actor
|
||||
def multiply(x, y):
|
||||
return x * y
|
||||
|
||||
broker.declare_actor(count_words)
|
||||
|
||||
multiply.send(43, 51)
|
||||
|
||||
"""
|
||||
from typing import Collection
|
||||
|
||||
from remoulade import Middleware, broker
|
||||
|
||||
from opentelemetry import trace
|
||||
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
||||
from opentelemetry.instrumentation.remoulade import utils
|
||||
from opentelemetry.instrumentation.remoulade.package import _instruments
|
||||
from opentelemetry.instrumentation.remoulade.version import __version__
|
||||
from opentelemetry.propagate import extract, inject
|
||||
from opentelemetry.semconv.trace import SpanAttributes
|
||||
|
||||
_REMOULADE_MESSAGE_TAG_KEY = "remoulade.action"
|
||||
_REMOULADE_MESSAGE_SEND = "send"
|
||||
_REMOULADE_MESSAGE_RUN = "run"
|
||||
|
||||
_REMOULADE_MESSAGE_NAME_KEY = "remoulade.actor_name"
|
||||
|
||||
_REMOULADE_MESSAGE_RETRY_COUNT_KEY = "remoulade.retry_count"
|
||||
|
||||
|
||||
class _InstrumentationMiddleware(Middleware):
|
||||
def __init__(self, _tracer):
|
||||
self._tracer = _tracer
|
||||
self._span_registry = {}
|
||||
|
||||
def before_process_message(self, _broker, message):
|
||||
if "trace_ctx" not in message.options:
|
||||
return
|
||||
|
||||
trace_ctx = extract(message.options["trace_ctx"])
|
||||
retry_count = message.options.get("retries", 0)
|
||||
operation_name = utils.get_operation_name(
|
||||
"before_process_message", retry_count
|
||||
)
|
||||
span_attributes = {_REMOULADE_MESSAGE_RETRY_COUNT_KEY: retry_count}
|
||||
|
||||
span = self._tracer.start_span(
|
||||
operation_name,
|
||||
kind=trace.SpanKind.CONSUMER,
|
||||
context=trace_ctx,
|
||||
attributes=span_attributes,
|
||||
)
|
||||
|
||||
activation = trace.use_span(span, end_on_exit=True)
|
||||
activation.__enter__() # pylint: disable=E1101
|
||||
|
||||
utils.attach_span(
|
||||
self._span_registry, message.message_id, (span, activation)
|
||||
)
|
||||
|
||||
def after_process_message(
|
||||
self, _broker, message, *, result=None, exception=None
|
||||
):
|
||||
span, activation = utils.retrieve_span(
|
||||
self._span_registry, message.message_id
|
||||
)
|
||||
|
||||
if span is None:
|
||||
# no existing span found for message_id
|
||||
return
|
||||
|
||||
if span.is_recording():
|
||||
span.set_attributes(
|
||||
{
|
||||
_REMOULADE_MESSAGE_TAG_KEY: _REMOULADE_MESSAGE_RUN,
|
||||
_REMOULADE_MESSAGE_NAME_KEY: message.actor_name,
|
||||
SpanAttributes.MESSAGING_MESSAGE_ID: message.message_id,
|
||||
}
|
||||
)
|
||||
|
||||
activation.__exit__(None, None, None)
|
||||
utils.detach_span(self._span_registry, message.message_id)
|
||||
|
||||
def before_enqueue(self, _broker, message, delay):
|
||||
retry_count = message.options.get("retries", 0)
|
||||
operation_name = utils.get_operation_name(
|
||||
"before_enqueue", retry_count
|
||||
)
|
||||
span_attributes = {_REMOULADE_MESSAGE_RETRY_COUNT_KEY: retry_count}
|
||||
|
||||
span = self._tracer.start_span(
|
||||
operation_name,
|
||||
kind=trace.SpanKind.PRODUCER,
|
||||
attributes=span_attributes,
|
||||
)
|
||||
|
||||
if span.is_recording():
|
||||
span.set_attributes(
|
||||
{
|
||||
_REMOULADE_MESSAGE_TAG_KEY: _REMOULADE_MESSAGE_SEND,
|
||||
_REMOULADE_MESSAGE_NAME_KEY: message.actor_name,
|
||||
SpanAttributes.MESSAGING_MESSAGE_ID: message.message_id,
|
||||
}
|
||||
)
|
||||
|
||||
activation = trace.use_span(span, end_on_exit=True)
|
||||
activation.__enter__() # pylint: disable=E1101
|
||||
|
||||
utils.attach_span(
|
||||
self._span_registry,
|
||||
message.message_id,
|
||||
(span, activation),
|
||||
is_publish=True,
|
||||
)
|
||||
|
||||
if "trace_ctx" not in message.options:
|
||||
message.options["trace_ctx"] = {}
|
||||
inject(message.options["trace_ctx"])
|
||||
|
||||
def after_enqueue(self, _broker, message, delay, exception=None):
|
||||
_, activation = utils.retrieve_span(
|
||||
self._span_registry, message.message_id, is_publish=True
|
||||
)
|
||||
|
||||
if activation is None:
|
||||
# no existing span found for message_id
|
||||
return
|
||||
|
||||
activation.__exit__(None, None, None)
|
||||
utils.detach_span(
|
||||
self._span_registry, message.message_id, is_publish=True
|
||||
)
|
||||
|
||||
|
||||
class RemouladeInstrumentor(BaseInstrumentor):
|
||||
def instrumentation_dependencies(self) -> Collection[str]:
|
||||
return _instruments
|
||||
|
||||
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)
|
||||
instrumentation_middleware = _InstrumentationMiddleware(self._tracer)
|
||||
|
||||
broker.add_extra_default_middleware(instrumentation_middleware)
|
||||
|
||||
def _uninstrument(self, **kwargs):
|
||||
broker.remove_extra_default_middleware(_InstrumentationMiddleware)
|
@ -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.
|
||||
|
||||
_instruments = ("remoulade >= 0.50",)
|
@ -0,0 +1,43 @@
|
||||
# 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.
|
||||
|
||||
|
||||
def attach_span(
|
||||
span_registry, message_id, span_and_activation, is_publish=False
|
||||
):
|
||||
span_registry[(message_id, is_publish)] = span_and_activation
|
||||
|
||||
|
||||
def detach_span(span_registry, message_id, is_publish=False):
|
||||
span_registry.pop((message_id, is_publish))
|
||||
|
||||
|
||||
def retrieve_span(span_registry, message_id, is_publish=False):
|
||||
return span_registry.get((message_id, is_publish), (None, None))
|
||||
|
||||
|
||||
def get_operation_name(hook_name, retry_count):
|
||||
if hook_name == "before_process_message":
|
||||
return (
|
||||
"remoulade/process"
|
||||
if retry_count == 0
|
||||
else f"remoulade/process(retry-{retry_count})"
|
||||
)
|
||||
if hook_name == "before_enqueue":
|
||||
return (
|
||||
"remoulade/send"
|
||||
if retry_count == 0
|
||||
else f"remoulade/send(retry-{retry_count})"
|
||||
)
|
||||
return ""
|
@ -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__ = "0.31b0"
|
@ -0,0 +1,100 @@
|
||||
# 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 remoulade
|
||||
from remoulade.brokers.local import LocalBroker
|
||||
|
||||
from opentelemetry.instrumentation.remoulade import RemouladeInstrumentor
|
||||
from opentelemetry.test.test_base import TestBase
|
||||
from opentelemetry.trace import SpanKind
|
||||
|
||||
|
||||
@remoulade.actor(max_retries=3)
|
||||
def actor_div(dividend, divisor):
|
||||
return dividend / divisor
|
||||
|
||||
|
||||
class TestRemouladeInstrumentation(TestBase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
RemouladeInstrumentor().instrument()
|
||||
|
||||
broker = LocalBroker()
|
||||
remoulade.set_broker(broker)
|
||||
|
||||
broker.declare_actor(actor_div)
|
||||
|
||||
def test_message(self):
|
||||
actor_div.send(2, 3)
|
||||
|
||||
spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
|
||||
self.assertEqual(len(spans), 2)
|
||||
|
||||
consumer, producer = spans
|
||||
|
||||
self.assertEqual(consumer.name, "remoulade/process")
|
||||
self.assertEqual(consumer.kind, SpanKind.CONSUMER)
|
||||
self.assertSpanHasAttributes(
|
||||
consumer,
|
||||
{
|
||||
"remoulade.action": "run",
|
||||
"remoulade.actor_name": "actor_div",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(producer.name, "remoulade/send")
|
||||
self.assertEqual(producer.kind, SpanKind.PRODUCER)
|
||||
self.assertSpanHasAttributes(
|
||||
producer,
|
||||
{
|
||||
"remoulade.action": "send",
|
||||
"remoulade.actor_name": "actor_div",
|
||||
},
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
def test_retries(self):
|
||||
try:
|
||||
actor_div.send(1, 0)
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
|
||||
spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
|
||||
self.assertEqual(len(spans), 8)
|
||||
|
||||
consumer_spans = spans[::2]
|
||||
producer_spans = spans[1::2]
|
||||
|
||||
self.assertEqual(consumer_spans[0].name, "remoulade/process(retry-3)")
|
||||
self.assertSpanHasAttributes(
|
||||
consumer_spans[0], {"remoulade.retry_count": 3}
|
||||
)
|
||||
self.assertEqual(consumer_spans[1].name, "remoulade/process(retry-2)")
|
||||
self.assertSpanHasAttributes(
|
||||
consumer_spans[1], {"remoulade.retry_count": 2}
|
||||
)
|
||||
self.assertEqual(consumer_spans[3].name, "remoulade/process")
|
||||
|
||||
self.assertEqual(producer_spans[0].name, "remoulade/send(retry-3)")
|
||||
self.assertSpanHasAttributes(
|
||||
producer_spans[0], {"remoulade.retry_count": 3}
|
||||
)
|
||||
self.assertEqual(producer_spans[1].name, "remoulade/send(retry-2)")
|
||||
self.assertSpanHasAttributes(
|
||||
producer_spans[1], {"remoulade.retry_count": 2}
|
||||
)
|
||||
self.assertEqual(producer_spans[3].name, "remoulade/send")
|
@ -0,0 +1,57 @@
|
||||
# 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 remoulade
|
||||
from remoulade.brokers.local import LocalBroker
|
||||
|
||||
from opentelemetry.instrumentation.remoulade import RemouladeInstrumentor
|
||||
from opentelemetry.test.test_base import TestBase
|
||||
|
||||
|
||||
@remoulade.actor(max_retries=3)
|
||||
def actor_div(dividend, divisor):
|
||||
return dividend / divisor
|
||||
|
||||
|
||||
class TestRemouladeUninstrumentation(TestBase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
RemouladeInstrumentor().instrument()
|
||||
|
||||
broker = LocalBroker()
|
||||
remoulade.set_broker(broker)
|
||||
broker.declare_actor(actor_div)
|
||||
|
||||
RemouladeInstrumentor().uninstrument()
|
||||
|
||||
def test_uninstrument_existing_broker(self):
|
||||
actor_div.send(1, 1)
|
||||
spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
|
||||
self.assertEqual(len(spans), 0)
|
||||
|
||||
def test_uninstrument_new_brokers(self):
|
||||
new_broker = LocalBroker()
|
||||
remoulade.set_broker(new_broker)
|
||||
new_broker.declare_actor(actor_div)
|
||||
|
||||
actor_div.send(1, 1)
|
||||
spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
|
||||
self.assertEqual(len(spans), 0)
|
||||
|
||||
def test_reinstrument_existing_broker(self):
|
||||
RemouladeInstrumentor().instrument()
|
||||
|
||||
actor_div.send(1, 1)
|
||||
spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
|
||||
self.assertEqual(len(spans), 2)
|
@ -56,6 +56,7 @@ install_requires =
|
||||
opentelemetry-instrumentation-pymysql==0.31b0
|
||||
opentelemetry-instrumentation-pyramid==0.31b0
|
||||
opentelemetry-instrumentation-redis==0.31b0
|
||||
opentelemetry-instrumentation-remoulade==0.31b0
|
||||
opentelemetry-instrumentation-requests==0.31b0
|
||||
opentelemetry-instrumentation-sklearn==0.31b0
|
||||
opentelemetry-instrumentation-sqlalchemy==0.31b0
|
||||
|
@ -116,6 +116,10 @@ libraries = {
|
||||
"library": "redis >= 2.6",
|
||||
"instrumentation": "opentelemetry-instrumentation-redis==0.31b0",
|
||||
},
|
||||
"remoulade": {
|
||||
"library": "remoulade >= 0.50",
|
||||
"instrumentation": "opentelemetry-instrumentation-remoulade==0.31b0",
|
||||
},
|
||||
"requests": {
|
||||
"library": "requests ~= 2.0",
|
||||
"instrumentation": "opentelemetry-instrumentation-requests==0.31b0",
|
||||
|
11
tox.ini
11
tox.ini
@ -153,6 +153,11 @@ envlist =
|
||||
py3{6,7,8,9,10}-test-instrumentation-redis
|
||||
pypy3-test-instrumentation-redis
|
||||
|
||||
; opentelemetry-instrumentation-remoulade
|
||||
; remoulade only supports 3.7 and above
|
||||
py3{7,8,9,10}-test-instrumentation-remoulade
|
||||
; instrumentation-remoulade intentionally excluded from pypy3
|
||||
|
||||
; opentelemetry-instrumentation-celery
|
||||
py3{6,7,8,9,10}-test-instrumentation-celery
|
||||
pypy3-test-instrumentation-celery
|
||||
@ -275,6 +280,7 @@ changedir =
|
||||
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-remoulade: instrumentation/opentelemetry-instrumentation-remoulade/tests
|
||||
test-instrumentation-requests: instrumentation/opentelemetry-instrumentation-requests/tests
|
||||
test-instrumentation-sklearn: instrumentation/opentelemetry-instrumentation-sklearn/tests
|
||||
test-instrumentation-sqlalchemy{11,14}: instrumentation/opentelemetry-instrumentation-sqlalchemy/tests
|
||||
@ -354,6 +360,8 @@ commands_pre =
|
||||
|
||||
redis: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-redis[test]
|
||||
|
||||
remoulade: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-remoulade[test]
|
||||
|
||||
requests: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-requests[test]
|
||||
|
||||
starlette: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-starlette[test]
|
||||
@ -448,6 +456,7 @@ commands_pre =
|
||||
python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-pika[test]
|
||||
python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-sklearn[test]
|
||||
python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-redis[test]
|
||||
python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-remoulade[test]
|
||||
python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-fastapi[test]
|
||||
python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-jinja2[test]
|
||||
python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-kafka-python[test]
|
||||
@ -497,6 +506,7 @@ deps =
|
||||
requests==2.25.0
|
||||
pyodbc~=4.0.30
|
||||
flaky==3.7.0
|
||||
remoulade>=0.50
|
||||
|
||||
changedir =
|
||||
tests/opentelemetry-docker-tests/tests
|
||||
@ -519,6 +529,7 @@ commands_pre =
|
||||
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-sqlalchemy \
|
||||
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-aiopg \
|
||||
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-redis \
|
||||
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-remoulade \
|
||||
"{env:CORE_REPO}#egg=opentelemetry-exporter-opencensus&subdirectory=exporter/opentelemetry-exporter-opencensus"
|
||||
docker-compose up -d
|
||||
python check_availability.py
|
||||
|
Reference in New Issue
Block a user