Skip to content

Commit b6a1c03

Browse files
Merge pull request #5 from carlosalberto/extra_clean_checks
Extra clean checks
2 parents 0bf325d + 9313e3b commit b6a1c03

5 files changed

Lines changed: 103 additions & 30 deletions

File tree

NOTES.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,14 @@ exists for both Connection and Session objects. Sadly, such dictionary
7070
is 'moved' around for every Connection of the parent Engine, thus is
7171
not unique, thus we can't use it for thread scenarios.
7272

73-
One alternative was also to have thread local objects - specifically
73+
A second alternative is to use a weak dictionary - so we keep
74+
the statements/connection/session around, and even if they are
75+
used/ignored/forgotten, we don't keep them around forever. This is
76+
similar to what the Django/Flask/Pyramid connectors do, with the
77+
exception of them having a well defined lifetime for the decorated
78+
objects (the request one).
79+
80+
A third alternative was also to have thread local objects - specifically
7481
to hold the current active span. While this may have worked just fine
7582
for us, this is something that has been done and re-done in other
7683
OT libraries/language. Thus we will wait to see how the eventual

sqlalchemy_opentracing/__init__.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,24 @@
44

55
g_tracer = None
66
g_trace_all_queries = False
7+
g_trace_all_engines = False
78

89
def init_tracing(tracer, trace_all_engines=False, trace_all_queries=False):
910
'''
1011
Set our global tracer.
1112
Tracer objects from our pyramid/flask/django libraries
1213
can be passed as well.
1314
'''
14-
global g_tracer, g_trace_all_queries
15+
global g_tracer, g_trace_all_engines, g_trace_all_queries
16+
1517
if hasattr(tracer, '_tracer'):
16-
g_tracer = tracer._tracer
18+
tracer = tracer._tracer
1719
else:
18-
g_tracer = tracer
20+
tracer = tracer
1921

22+
g_tracer = tracer
2023
g_trace_all_queries = trace_all_queries
24+
g_trace_all_engines = trace_all_engines
2125

2226
if trace_all_engines:
2327
register_engine(Engine)
@@ -79,6 +83,11 @@ def register_engine(obj):
7983
'''
8084
Register an engine to have its events be traced.
8185
'''
86+
if g_tracer is None:
87+
raise RuntimeError('The tracer is not properly set')
88+
if g_trace_all_engines and obj != Engine:
89+
raise RuntimeError('Tracing all engines already')
90+
8291
listen(obj, 'before_cursor_execute', _engine_before_cursor_handler)
8392
listen(obj, 'after_cursor_execute', _engine_after_cursor_handler)
8493
listen(obj, 'handle_error', _engine_error_handler)
@@ -91,6 +100,13 @@ def unregister_engine(obj):
91100
remove(obj, 'after_cursor_execute', _engine_after_cursor_handler)
92101
remove(obj, 'handle_error', _engine_error_handler)
93102

103+
def _clear_tracer():
104+
'''
105+
Set the tracer to None. For test cases usage.
106+
'''
107+
global g_tracer
108+
g_tracer = None
109+
94110
def _can_operation_be_traced(conn, stmt_obj):
95111
'''
96112
Get whether an operation can be traced, depending on its

tests/test_api.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import unittest
22
from mock import patch
33
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
4+
from sqlalchemy.engine import Engine
45
from sqlalchemy.exc import OperationalError
56
from sqlalchemy.schema import CreateTable
67

@@ -15,6 +16,9 @@ def setUp(self):
1516
Column('name', String),
1617
)
1718

19+
def tearDown(self):
20+
sqlalchemy_opentracing._clear_tracer()
21+
1822
def test_init(self):
1923
tracer = DummyTracer()
2024
sqlalchemy_opentracing.init_tracing(tracer)
@@ -64,3 +68,17 @@ def test_has_parent_none(self):
6468
self.assertEqual(False, sqlalchemy_opentracing.has_parent_span(stmt))
6569
self.assertEqual(None, sqlalchemy_opentracing.get_parent_span(stmt))
6670

71+
def test_register_no_tracer(self):
72+
engine = create_engine('sqlite:///:memory:')
73+
with self.assertRaises(RuntimeError):
74+
sqlalchemy_opentracing.register_engine(engine)
75+
76+
def test_register_dup(self):
77+
engine = create_engine('sqlite:///:memory:')
78+
sqlalchemy_opentracing.init_tracing(DummyTracer(), trace_all_engines=True)
79+
with self.assertRaises(RuntimeError):
80+
sqlalchemy_opentracing.register_engine(engine)
81+
82+
# Manually clear the Engine from listening events.
83+
sqlalchemy_opentracing.unregister_engine(Engine)
84+

tests/test_core.py

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ def setUp(self):
1515
Column('id', Integer, primary_key=True),
1616
Column('name', String),
1717
)
18-
sqlalchemy_opentracing.register_engine(self.engine)
18+
def tearDown(self):
19+
sqlalchemy_opentracing._clear_tracer()
1920

2021
def test_traced(self):
2122
tracer = DummyTracer()
22-
creat = CreateTable(self.users_table)
23-
2423
sqlalchemy_opentracing.init_tracing(tracer)
24+
sqlalchemy_opentracing.register_engine(self.engine)
25+
26+
creat = CreateTable(self.users_table)
2527
sqlalchemy_opentracing.set_traced(creat)
2628
self.engine.execute(creat)
2729

@@ -38,31 +40,32 @@ def test_traced(self):
3840

3941
def test_traced_none(self):
4042
tracer = DummyTracer()
41-
creat = CreateTable(self.users_table)
42-
4343
sqlalchemy_opentracing.init_tracing(tracer)
44+
sqlalchemy_opentracing.register_engine(self.engine)
45+
46+
creat = CreateTable(self.users_table)
4447
self.engine.execute(creat)
4548

4649
self.assertEqual(0, len(tracer.spans))
4750

4851
def test_traced_all_queries(self):
4952
tracer = DummyTracer()
50-
creat = CreateTable(self.users_table)
51-
5253
sqlalchemy_opentracing.init_tracing(tracer, trace_all_queries=True)
54+
sqlalchemy_opentracing.register_engine(self.engine)
55+
56+
creat = CreateTable(self.users_table)
5357
self.engine.execute(creat)
5458

5559
self.assertEqual(1, len(tracer.spans))
5660

5761
def test_traced_all_engines(self):
58-
# Create an engine that is not registered.
59-
e = create_engine('sqlite:///:memory:')
62+
# Don't register the engine explicitly.
6063
tracer = DummyTracer()
61-
creat = CreateTable(self.users_table)
62-
6364
sqlalchemy_opentracing.init_tracing(tracer, trace_all_engines=True)
65+
66+
creat = CreateTable(self.users_table)
6467
sqlalchemy_opentracing.set_traced(creat)
65-
e.execute(creat)
68+
self.engine.execute(creat)
6669

6770
# Unregister the main Engine class before doing our assertions,
6871
# in case we fail.
@@ -74,9 +77,10 @@ def test_traced_all_engines(self):
7477

7578
def test_traced_error(self):
7679
tracer = DummyTracer()
77-
creat = CreateTable(self.users_table)
78-
7980
sqlalchemy_opentracing.init_tracing(tracer)
81+
sqlalchemy_opentracing.register_engine(self.engine)
82+
83+
creat = CreateTable(self.users_table)
8084
self.engine.execute(creat)
8185
self.assertEqual(0, len(tracer.spans))
8286

@@ -100,8 +104,9 @@ def test_traced_error(self):
100104

101105
def test_trace_text(self):
102106
tracer = DummyTracer()
103-
104107
sqlalchemy_opentracing.init_tracing(tracer, trace_all_queries=True)
108+
sqlalchemy_opentracing.register_engine(self.engine)
109+
105110
self.engine.execute('CREATE TABLE users (id INTEGER NOT NULL, name VARCHAR, PRIMARY KEY (id))')
106111
self.assertEqual(1, len(tracer.spans))
107112
self.assertEqual(tracer.spans[0].operation_name, 'textclause')
@@ -115,8 +120,9 @@ def test_trace_text(self):
115120

116121
def test_trace_text_error(self):
117122
tracer = DummyTracer()
118-
119123
sqlalchemy_opentracing.init_tracing(tracer, trace_all_queries=True)
124+
sqlalchemy_opentracing.register_engine(self.engine)
125+
120126
try:
121127
self.engine.execute('SELECT name FROM users')
122128
except OperationalError:
@@ -136,11 +142,13 @@ def test_trace_text_error(self):
136142

137143
def test_traced_transaction(self):
138144
tracer = DummyTracer()
145+
sqlalchemy_opentracing.init_tracing(tracer)
146+
sqlalchemy_opentracing.register_engine(self.engine)
147+
139148
creat = CreateTable(self.users_table)
140149
ins = self.users_table.insert().values(name='John Doe')
141150
sel = select([self.users_table])
142151

143-
sqlalchemy_opentracing.init_tracing(tracer)
144152
parent_span = DummySpan('parent span')
145153
conn = self.engine.connect()
146154
with conn.begin() as trans:
@@ -157,11 +165,13 @@ def test_traced_transaction(self):
157165

158166
def test_traced_transaction_nested(self):
159167
tracer = DummyTracer()
168+
sqlalchemy_opentracing.init_tracing(tracer)
169+
sqlalchemy_opentracing.register_engine(self.engine)
170+
160171
creat = CreateTable(self.users_table)
161172
ins = self.users_table.insert().values(name='John Doe')
162173
sel = select([self.users_table])
163174

164-
sqlalchemy_opentracing.init_tracing(tracer)
165175
parent_span = DummySpan('parent span')
166176
conn = self.engine.connect()
167177

@@ -181,13 +191,15 @@ def test_traced_transaction_nested(self):
181191

182192
def test_traced_rollback(self):
183193
tracer = DummyTracer()
194+
sqlalchemy_opentracing.init_tracing(tracer)
195+
sqlalchemy_opentracing.register_engine(self.engine)
196+
184197
creat = CreateTable(self.users_table)
185198
ins = self.users_table.insert().values(name='John Doe')
186199

187200
# Don't trace this.
188201
self.engine.execute(creat)
189202

190-
sqlalchemy_opentracing.init_tracing(tracer)
191203
parent_span = DummySpan('parent span')
192204
conn = self.engine.connect()
193205
try:
@@ -208,9 +220,11 @@ def test_traced_rollback(self):
208220

209221
def test_traced_after_transaction(self):
210222
tracer = DummyTracer()
223+
sqlalchemy_opentracing.init_tracing(tracer)
224+
sqlalchemy_opentracing.register_engine(self.engine)
225+
211226
creat = CreateTable(self.users_table)
212227

213-
sqlalchemy_opentracing.init_tracing(tracer)
214228
conn = self.engine.connect()
215229
with conn.begin() as tx:
216230
sqlalchemy_opentracing.set_traced(conn)
@@ -229,10 +243,12 @@ def test_traced_after_transaction(self):
229243

230244
def test_traced_after_rollback(self):
231245
tracer = DummyTracer()
246+
sqlalchemy_opentracing.init_tracing(tracer)
247+
sqlalchemy_opentracing.register_engine(self.engine)
248+
232249
creat = CreateTable(self.users_table)
233250

234251
# Create a table, but don't trace it
235-
sqlalchemy_opentracing.init_tracing(tracer)
236252
conn = self.engine.connect()
237253
with conn.begin() as tx:
238254
conn.execute(creat)
@@ -257,11 +273,12 @@ def test_traced_after_rollback(self):
257273

258274
def test_traced_clear_connection(self):
259275
tracer = DummyTracer()
276+
sqlalchemy_opentracing.init_tracing(tracer)
277+
sqlalchemy_opentracing.register_engine(self.engine)
278+
260279
creat = CreateTable(self.users_table)
261280
ins = self.users_table.insert().values(name='John Doe')
262281

263-
sqlalchemy_opentracing.init_tracing(tracer)
264-
265282
conn = self.engine.connect()
266283
with conn.begin() as tx:
267284
sqlalchemy_opentracing.set_traced(conn)
@@ -277,9 +294,10 @@ def test_traced_clear_connection(self):
277294

278295
def test_unregister_engine(self):
279296
tracer = DummyTracer()
280-
creat = CreateTable(self.users_table)
281-
282297
sqlalchemy_opentracing.init_tracing(tracer, trace_all_queries=True)
298+
sqlalchemy_opentracing.register_engine(self.engine)
299+
300+
creat = CreateTable(self.users_table)
283301
self.engine.execute(creat)
284302
self.assertEqual(1, len(tracer.spans))
285303

0 commit comments

Comments
 (0)