Skip to content

Commit ebb4145

Browse files
authored
Merge branch 'main' into intrument-mysqlclient
2 parents b1168f8 + 46e4b1d commit ebb4145

File tree

12 files changed

+89
-14
lines changed

12 files changed

+89
-14
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
- `opentelemetry-instrumentation-system-metrics` Add `process.` prefix to `runtime.memory`, `runtime.cpu.time`, and `runtime.gc_count`. Change `runtime.memory` from count to UpDownCounter. ([#1735](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1735))
1111
- Add request and response hooks for GRPC instrumentation (client only)
1212
([#1706](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1706))
13+
- `opentelemetry-instrumentation-pymemcache` Update instrumentation to support pymemcache >4
14+
([#1764](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1764))
1315

1416
### Added
1517

@@ -19,6 +21,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1921
([#1730](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1730))
2022
- `opentelemetry-instrumentation-mysqlclient` Add instrumentor support for mysqlclient
2123
([#1744](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1744))
24+
- Make ASGI request span attributes available for `start_span`.
25+
([#1762](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1762))
26+
- `opentelemetry-instrumentation-celery` Add support for anonymous tasks.
27+
([#1407](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1407)
28+
2229

2330
### Fixed
2431

instrumentation/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
| [opentelemetry-instrumentation-mysqlclient](./opentelemetry-instrumentation-mysqlclient) | mysqlclient < 3 | No
2828
| [opentelemetry-instrumentation-pika](./opentelemetry-instrumentation-pika) | pika >= 0.12.0 | No
2929
| [opentelemetry-instrumentation-psycopg2](./opentelemetry-instrumentation-psycopg2) | psycopg2 >= 2.7.3.1 | No
30-
| [opentelemetry-instrumentation-pymemcache](./opentelemetry-instrumentation-pymemcache) | pymemcache >= 1.3.5, < 4 | No
30+
| [opentelemetry-instrumentation-pymemcache](./opentelemetry-instrumentation-pymemcache) | pymemcache >= 1.3.5, < 5 | No
3131
| [opentelemetry-instrumentation-pymongo](./opentelemetry-instrumentation-pymongo) | pymongo >= 3.1, < 5.0 | No
3232
| [opentelemetry-instrumentation-pymysql](./opentelemetry-instrumentation-pymysql) | PyMySQL < 2 | No
3333
| [opentelemetry-instrumentation-pyramid](./opentelemetry-instrumentation-pyramid) | pyramid >= 1.7 | Yes

instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def test_status_codes(self):
122122
(span_status, None),
123123
{
124124
SpanAttributes.HTTP_METHOD: "GET",
125-
SpanAttributes.HTTP_URL: f"http://{host}:{port}/test-path?query=param#foobar",
125+
SpanAttributes.HTTP_URL: f"http://{host}:{port}/test-path#foobar",
126126
SpanAttributes.HTTP_STATUS_CODE: int(
127127
status_code
128128
),

instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -531,15 +531,16 @@ async def __call__(self, scope, receive, send):
531531

532532
span_name, additional_attributes = self.default_span_details(scope)
533533

534+
attributes = collect_request_attributes(scope)
535+
attributes.update(additional_attributes)
534536
span, token = _start_internal_or_server_span(
535537
tracer=self.tracer,
536538
span_name=span_name,
537539
start_time=None,
538540
context_carrier=scope,
539541
context_getter=asgi_getter,
542+
attributes=attributes,
540543
)
541-
attributes = collect_request_attributes(scope)
542-
attributes.update(additional_attributes)
543544
active_requests_count_attrs = _parse_active_request_count_attrs(
544545
attributes
545546
)

instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,17 @@ def _trace_before_publish(self, *args, **kwargs):
183183
task = utils.retrieve_task_from_sender(kwargs)
184184
task_id = utils.retrieve_task_id_from_message(kwargs)
185185

186-
if task is None or task_id is None:
186+
if task_id is None:
187187
return
188188

189-
operation_name = f"{_TASK_APPLY_ASYNC}/{task.name}"
189+
if task is None:
190+
# task is an anonymous task send using send_task or using canvas workflow
191+
# Signatures() to send to a task not in the current processes dependency
192+
# tree
193+
task_name = kwargs.get("sender", "unknown")
194+
else:
195+
task_name = task.name
196+
operation_name = f"{_TASK_APPLY_ASYNC}/{task_name}"
190197
span = self._tracer.start_span(
191198
operation_name, kind=trace.SpanKind.PRODUCER
192199
)
@@ -195,7 +202,7 @@ def _trace_before_publish(self, *args, **kwargs):
195202
if span.is_recording():
196203
span.set_attribute(_TASK_TAG_KEY, _TASK_APPLY_ASYNC)
197204
span.set_attribute(SpanAttributes.MESSAGING_MESSAGE_ID, task_id)
198-
span.set_attribute(_TASK_NAME_KEY, task.name)
205+
span.set_attribute(_TASK_NAME_KEY, task_name)
199206
utils.set_attributes_from_context(span, kwargs)
200207

201208
activation = trace.use_span(span, end_on_exit=True)

instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py

+2
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ def attach_span(task, task_id, span, is_publish=False):
132132
NOTE: We cannot test for this well yet, because we do not run a celery worker,
133133
and cannot run `task.apply_async()`
134134
"""
135+
if task is None:
136+
return
135137
span_dict = getattr(task, CTX_KEY, None)
136138
if span_dict is None:
137139
span_dict = {}

instrumentation/opentelemetry-instrumentation-celery/tests/test_tasks.py

+50
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def tearDown(self):
3636
CeleryInstrumentor().uninstrument()
3737
self._worker.stop()
3838
self._thread.join()
39+
CeleryInstrumentor().uninstrument()
3940

4041
def test_task(self):
4142
CeleryInstrumentor().instrument()
@@ -97,3 +98,52 @@ def test_uninstrument(self):
9798

9899
spans = self.memory_exporter.get_finished_spans()
99100
self.assertEqual(len(spans), 0)
101+
102+
103+
class TestCelerySignatureTask(TestBase):
104+
def setUp(self):
105+
super().setUp()
106+
107+
def start_app(*args, **kwargs):
108+
# Add an additional task that will not be registered with parent thread
109+
@app.task
110+
def hidden_task(num_a):
111+
return num_a * 2
112+
113+
self._worker = app.Worker(app=app, pool="solo", concurrency=1)
114+
return self._worker.start(*args, **kwargs)
115+
116+
self._thread = threading.Thread(target=start_app)
117+
self._worker = app.Worker(app=app, pool="solo", concurrency=1)
118+
self._thread.daemon = True
119+
self._thread.start()
120+
121+
def tearDown(self):
122+
super().tearDown()
123+
self._worker.stop()
124+
self._thread.join()
125+
CeleryInstrumentor().uninstrument()
126+
127+
def test_hidden_task(self):
128+
# no-op since already instrumented
129+
CeleryInstrumentor().instrument()
130+
131+
res = app.signature("tests.test_tasks.hidden_task", (2,)).apply_async()
132+
while not res.ready():
133+
time.sleep(0.05)
134+
spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
135+
self.assertEqual(len(spans), 2)
136+
137+
consumer, producer = spans
138+
139+
self.assertEqual(consumer.name, "run/tests.test_tasks.hidden_task")
140+
self.assertEqual(consumer.kind, SpanKind.CONSUMER)
141+
142+
self.assertEqual(
143+
producer.name, "apply_async/tests.test_tasks.hidden_task"
144+
)
145+
self.assertEqual(producer.kind, SpanKind.PRODUCER)
146+
147+
self.assertNotEqual(consumer.parent, producer.context)
148+
self.assertEqual(consumer.parent.span_id, producer.context.span_id)
149+
self.assertEqual(consumer.context.trace_id, producer.context.trace_id)

instrumentation/opentelemetry-instrumentation-celery/tests/test_utils.py

+7
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,13 @@ def fn_task():
185185
utils.detach_span(fn_task, task_id)
186186
self.assertEqual(utils.retrieve_span(fn_task, task_id), (None, None))
187187

188+
def test_optional_task_span_attach(self):
189+
task_id = "7c6731af-9533-40c3-83a9-25b58f0d837f"
190+
span = trace._Span("name", mock.Mock(spec=trace_api.SpanContext))
191+
192+
# assert this is is a no-aop
193+
self.assertIsNone(utils.attach_span(None, task_id, span))
194+
188195
def test_span_delete_empty(self):
189196
# ensure detach_span doesn't raise an exception if span is not present
190197
@self.app.task

instrumentation/opentelemetry-instrumentation-pymemcache/pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ dependencies = [
3333

3434
[project.optional-dependencies]
3535
instruments = [
36-
"pymemcache >= 1.3.5, < 4",
36+
"pymemcache >= 1.3.5, < 5",
3737
]
3838
test = [
3939
"opentelemetry-instrumentation-pymemcache[instruments]",

instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/package.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
# limitations under the License.
1414

1515

16-
_instruments = ("pymemcache >= 1.3.5, < 4",)
16+
_instruments = ("pymemcache >= 1.3.5, < 5",)

opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@
109109
"instrumentation": "opentelemetry-instrumentation-psycopg2==0.39b0.dev",
110110
},
111111
"pymemcache": {
112-
"library": "pymemcache >= 1.3.5, < 4",
112+
"library": "pymemcache >= 1.3.5, < 5",
113113
"instrumentation": "opentelemetry-instrumentation-pymemcache==0.39b0.dev",
114114
},
115115
"pymongo": {

tox.ini

+5-4
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ envlist =
126126
; ext-psycopg2 intentionally excluded from pypy3
127127

128128
; opentelemetry-instrumentation-pymemcache
129-
py3{7,8,9,10,11}-test-instrumentation-pymemcache{135,200,300,342}
130-
pypy3-test-instrumentation-pymemcache{135,200,300,342}
129+
py3{7,8,9,10,11}-test-instrumentation-pymemcache{135,200,300,342,400}
130+
pypy3-test-instrumentation-pymemcache{135,200,300,342,400}
131131

132132
; opentelemetry-instrumentation-pymongo
133133
py3{7,8,9,10,11}-test-instrumentation-pymongo
@@ -271,6 +271,7 @@ deps =
271271
pymemcache200: pymemcache >2.0.0,<3.0.0
272272
pymemcache300: pymemcache >3.0.0,<3.4.2
273273
pymemcache342: pymemcache ==3.4.2
274+
pymemcache400: pymemcache ==4.0.0
274275
httpx18: httpx>=0.18.0,<0.19.0
275276
httpx18: respx~=0.17.0
276277
httpx21: httpx>=0.19.0
@@ -316,7 +317,7 @@ changedir =
316317
test-instrumentation-pika{0,1}: instrumentation/opentelemetry-instrumentation-pika/tests
317318
test-instrumentation-aio-pika{7,8,9}: instrumentation/opentelemetry-instrumentation-aio-pika/tests
318319
test-instrumentation-psycopg2: instrumentation/opentelemetry-instrumentation-psycopg2/tests
319-
test-instrumentation-pymemcache{135,200,300,342}: instrumentation/opentelemetry-instrumentation-pymemcache/tests
320+
test-instrumentation-pymemcache{135,200,300,342,400}: instrumentation/opentelemetry-instrumentation-pymemcache/tests
320321
test-instrumentation-pymongo: instrumentation/opentelemetry-instrumentation-pymongo/tests
321322
test-instrumentation-pymysql: instrumentation/opentelemetry-instrumentation-pymysql/tests
322323
test-instrumentation-pyramid: instrumentation/opentelemetry-instrumentation-pyramid/tests
@@ -397,7 +398,7 @@ commands_pre =
397398

398399
mysqlclient: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi {toxinidir}/instrumentation/opentelemetry-instrumentation-mysqlclient[test]
399400

400-
pymemcache{135,200,300,342}: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymemcache[test]
401+
pymemcache{135,200,300,342,400}: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymemcache[test]
401402

402403
pymongo: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymongo[test]
403404

0 commit comments

Comments
 (0)