Skip to content

Commit 251d07a

Browse files
authored
Merge pull request #2 from Charlie-lizhihan/bugfix-2639-dev
Bugfix 2639 dev
2 parents 99fab66 + bb00df7 commit 251d07a

File tree

1 file changed

+59
-22
lines changed
  • instrumentation/opentelemetry-instrumentation-redis/tests

1 file changed

+59
-22
lines changed

instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py

+59-22
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
import asyncio
15-
from unittest import mock
16-
from unittest.mock import AsyncMock
1715

16+
import pytest
1817
import redis
19-
import redis.asyncio
18+
import redis.asyncio as redis_async
2019
from redis.exceptions import WatchError
20+
from unittest import mock, IsolatedAsyncioTestCase
21+
from unittest.mock import AsyncMock
2122

2223
from opentelemetry import trace
2324
from opentelemetry.instrumentation.redis import RedisInstrumentor
@@ -27,7 +28,7 @@
2728
SpanAttributes,
2829
)
2930
from opentelemetry.test.test_base import TestBase
30-
from opentelemetry.trace import SpanKind, StatusCode
31+
from opentelemetry.trace import SpanKind
3132

3233

3334
class TestRedis(TestBase):
@@ -144,7 +145,7 @@ def response_hook(span, conn, response):
144145

145146
with mock.patch.object(connection, "send_command"):
146147
with mock.patch.object(
147-
redis_client, "parse_response", return_value=test_value
148+
redis_client, "parse_response", return_value=test_value
148149
):
149150
redis_client.get("key")
150151

@@ -176,7 +177,7 @@ def request_hook(span, conn, args, kwargs):
176177

177178
with mock.patch.object(connection, "send_command"):
178179
with mock.patch.object(
179-
redis_client, "parse_response", return_value=test_value
180+
redis_client, "parse_response", return_value=test_value
180181
):
181182
redis_client.get("key")
182183

@@ -313,24 +314,26 @@ def test_attributes_unix_socket(self):
313314
NetTransportValues.OTHER.value,
314315
)
315316

316-
def test_watch_error(self):
317+
def test_successful_transaction(self):
317318
redis_client = redis.Redis()
318319

319-
# Mock the pipeline to raise a WatchError
320+
# Create a mock pipeline
320321
mock_pipeline = mock.MagicMock()
322+
mock_pipeline.__enter__.return_value = mock_pipeline # Ensure __enter__ returns the mock_pipeline
321323
mock_pipeline.watch.return_value = None
322324
mock_pipeline.multi.return_value = mock_pipeline
323-
mock_pipeline.execute.side_effect = WatchError("Watched variable changed")
325+
mock_pipeline.execute.return_value = ["OK"] # This is what we want to return
324326

325327
with mock.patch.object(redis_client, "pipeline", return_value=mock_pipeline):
326-
try:
327-
with redis_client.pipeline() as pipe:
328-
pipe.watch("key")
329-
pipe.multi()
330-
pipe.set("key", "value")
331-
pipe.execute()
332-
except WatchError:
333-
pass # We expect this exception to be raised
328+
with redis_client.pipeline() as pipe:
329+
pipe.watch("key")
330+
pipe.multi()
331+
pipe.set("key", "value")
332+
result = pipe.execute()
333+
334+
# Check that the transaction was successful
335+
print(f"Result: {result}")
336+
self.assertEqual(result, ["OK"])
334337

335338
spans = self.memory_exporter.get_finished_spans()
336339
self.assertEqual(len(spans), 1)
@@ -339,14 +342,48 @@ def test_watch_error(self):
339342
# Check that the span is not marked as an error
340343
self.assertIsNone(span.status.status_code)
341344

342-
# Check that the WatchError is recorded as an event, not an exception
345+
# Check that there are no exception events
343346
events = span.events
344-
self.assertEqual(len(events), 1)
345-
self.assertEqual(events[0].name, "exception")
346-
self.assertEqual(events[0].attributes["exception.type"], "WatchError")
347-
self.assertIn("Watched variable changed", events[0].attributes["exception.message"])
347+
self.assertEqual(len(events), 0)
348348

349349
# Verify other span properties
350350
self.assertEqual(span.name, "MULTI")
351351
self.assertEqual(span.kind, SpanKind.CLIENT)
352352
self.assertEqual(span.attributes.get("db.system"), "redis")
353+
354+
# Verify that the SET command is recorded in the span
355+
self.assertIn("SET", span.attributes.get("db.statement", ""))
356+
357+
# Optionally, check for any additional attributes specific to your instrumentation
358+
# For example, you might want to verify that the database index is correctly recorded
359+
self.assertEqual(span.attributes.get("db.redis.database_index"), 0)
360+
361+
362+
class TestRedisAsync(TestBase, IsolatedAsyncioTestCase):
363+
def setUp(self):
364+
super().setUp()
365+
RedisInstrumentor().instrument(tracer_provider=self.tracer_provider)
366+
367+
def tearDown(self):
368+
super().tearDown()
369+
RedisInstrumentor().uninstrument()
370+
371+
@pytest.mark.asyncio
372+
async def test_redis_operations(self):
373+
async def redis_operations():
374+
try:
375+
r = redis_async.Redis()
376+
async with r.pipeline(transaction=False) as pipe:
377+
await pipe.watch("a")
378+
await r.set("a", "bad")
379+
pipe.multi()
380+
await pipe.set("a", "1")
381+
await pipe.execute()
382+
except WatchError:
383+
pass
384+
385+
await redis_operations()
386+
387+
spans = self.memory_exporter.get_finished_spans()
388+
assert spans[-1].status.status_code == trace.StatusCode.UNSET
389+
assert any(event.name == "WatchError" for event in spans[-1].events)

0 commit comments

Comments
 (0)