Skip to content

Commit c0b9ad7

Browse files
authored
added async_tracer support for pymongo instrumentation (#321)
Added async_tracer support for pymongo instrumentation * refactor the tracer discovery functionality into a tracer utility method
1 parent e5ad368 commit c0b9ad7

File tree

5 files changed

+38
-17
lines changed

5 files changed

+38
-17
lines changed

instana/instrumentation/pymongo.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,27 @@
44
from __future__ import absolute_import
55

66
from ..log import logger
7-
from ..singletons import tracer
7+
from ..util.traceutils import get_active_tracer
88

99
try:
1010
import pymongo
1111
from pymongo import monitoring
1212
from bson import json_util
1313

14+
1415
class MongoCommandTracer(monitoring.CommandListener):
1516
def __init__(self):
1617
self.__active_commands = {}
1718

1819
def started(self, event):
19-
parent_span = tracer.active_span
20-
20+
active_tracer = get_active_tracer()
2121
# return early if we're not tracing
22-
if parent_span is None:
22+
if active_tracer is None:
2323
return
2424

25-
with tracer.start_active_span("mongo", child_of=parent_span) as scope:
25+
parent_span = active_tracer.active_span
26+
27+
with active_tracer.start_active_span("mongo", child_of=parent_span) as scope:
2628
self._collect_connection_tags(scope.span, event)
2729
self._collect_command_tags(scope.span, event)
2830

@@ -79,7 +81,7 @@ def _collect_command_tags(self, span, event):
7981
cmd_doc = None
8082
if cmd in cmd_doc_locations:
8183
cmd_doc = event.command.get(cmd_doc_locations[cmd])
82-
elif cmd.lower() == "mapreduce": # mapreduce command was renamed to mapReduce in pymongo 3.9.0
84+
elif cmd.lower() == "mapreduce": # mapreduce command was renamed to mapReduce in pymongo 3.9.0
8385
# mapreduce command consists of two mandatory parts: map and reduce
8486
cmd_doc = {
8587
"map": event.command.get("map"),
@@ -89,6 +91,7 @@ def _collect_command_tags(self, span, event):
8991
if cmd_doc is not None:
9092
span.set_tag("json", json_util.dumps(cmd_doc))
9193

94+
9295
monitoring.register(MongoCommandTracer())
9396

9497
logger.debug("Instrumenting pymongo")

instana/singletons.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
agent = None
1313
tracer = None
14+
async_tracer = None
1415
profiler = None
1516
span_recorder = None
1617

@@ -79,11 +80,11 @@ def set_agent(new_agent):
7980
if sys.version_info >= (3, 4):
8081
try:
8182
from opentracing.scope_managers.asyncio import AsyncioScopeManager
83+
8284
async_tracer = InstanaTracer(scope_manager=AsyncioScopeManager(), recorder=span_recorder)
8385
except Exception:
8486
logger.debug("Error setting up async_tracer:", exc_info=True)
8587

86-
8788
# Mock the tornado tracer until tornado is detected and instrumented first
8889
tornado_tracer = tracer
8990

@@ -117,6 +118,7 @@ def set_tracer(new_tracer):
117118
global tracer
118119
tracer = new_tracer
119120

121+
120122
def get_profiler():
121123
"""
122124
Retrieve the globally configured profiler

instana/util/traceutils.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# (c) Copyright IBM Corp. 2021
22
# (c) Copyright Instana Inc. 2021
33

4-
from ..singletons import agent
4+
from ..singletons import agent, tracer, async_tracer
55
from ..log import logger
66

77

@@ -14,3 +14,16 @@ def extract_custom_headers(tracing_scope, headers):
1414
tracing_scope.span.set_tag("http.header.%s" % custom_header, value)
1515
except Exception as e:
1616
logger.debug("extract_custom_headers: ", exc_info=True)
17+
18+
19+
def get_active_tracer():
20+
try:
21+
if tracer.active_span:
22+
return tracer
23+
elif async_tracer.active_span:
24+
return async_tracer
25+
else:
26+
return None
27+
except Exception as e:
28+
logger.debug("error while getting active tracer: ", exc_info=True)
29+
return None

instana/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
# Module version file. Used by setup.py and snapshot reporting.
55

6-
VERSION = '1.33.1'
6+
VERSION = '1.33.2'

tests/clients/test_pymongo.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
logger = logging.getLogger(__name__)
2020

2121

22-
class TestPyMongo(unittest.TestCase):
22+
class TestPyMongoTracer(unittest.TestCase):
2323
def setUp(self):
2424
self.conn = pymongo.MongoClient(host=testenv['mongodb_host'], port=int(testenv['mongodb_port']),
2525
username=testenv['mongodb_user'], password=testenv['mongodb_pw'])
@@ -107,11 +107,11 @@ def test_successful_update_query(self):
107107

108108
payload = json.loads(db_span.data["mongo"]["json"])
109109
assert_true({
110-
"q": {"type": "string"},
111-
"u": {"$set": {"type": "int"}},
112-
"multi": False,
113-
"upsert": False
114-
} in payload, db_span.data["mongo"]["json"])
110+
"q": {"type": "string"},
111+
"u": {"$set": {"type": "int"}},
112+
"multi": False,
113+
"upsert": False
114+
} in payload, db_span.data["mongo"]["json"])
115115

116116
def test_successful_delete_query(self):
117117
with tracer.start_active_span("test"):
@@ -174,7 +174,8 @@ def test_successful_map_reduce_query(self):
174174
reducer = "function (key, values) { return len(values); }"
175175

176176
with tracer.start_active_span("test"):
177-
self.conn.test.records.map_reduce(bson.code.Code(mapper), bson.code.Code(reducer), "results", query={"x": {"$lt": 2}})
177+
self.conn.test.records.map_reduce(bson.code.Code(mapper), bson.code.Code(reducer), "results",
178+
query={"x": {"$lt": 2}})
178179

179180
assert_is_none(tracer.active_span)
180181

@@ -192,7 +193,8 @@ def test_successful_map_reduce_query(self):
192193
self.assertEqual(db_span.n, "mongo")
193194
self.assertEqual(db_span.data["mongo"]["service"], "%s:%s" % (testenv['mongodb_host'], testenv['mongodb_port']))
194195
self.assertEqual(db_span.data["mongo"]["namespace"], "test.records")
195-
self.assertEqual(db_span.data["mongo"]["command"].lower(), "mapreduce") # mapreduce command was renamed to mapReduce in pymongo 3.9.0
196+
self.assertEqual(db_span.data["mongo"]["command"].lower(),
197+
"mapreduce") # mapreduce command was renamed to mapReduce in pymongo 3.9.0
196198

197199
self.assertEqual(db_span.data["mongo"]["filter"], '{"x": {"$lt": 2}}')
198200
assert_is_not_none(db_span.data["mongo"]["json"])
@@ -228,3 +230,4 @@ def test_successful_mutiple_queries(self):
228230

229231
# ensure spans are ordered the same way as commands
230232
assert_list_equal(commands, ["insert", "update", "delete"])
233+

0 commit comments

Comments
 (0)