Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit bc604e7

Browse files
Gracefully handle log context slips and missing opentracing import errors. (#5988)
1 parent 1a6ae33 commit bc604e7

File tree

2 files changed

+59
-24
lines changed

2 files changed

+59
-24
lines changed

changelog.d/5988.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix invalid references to None while opentracing if the log context slips.

synapse/logging/opentracing.py

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,7 @@ class _DummyTagNames(object):
239239

240240

241241
def only_if_tracing(func):
242-
"""Executes the function only if we're tracing. Otherwise return.
243-
Assumes the function wrapped may return None"""
242+
"""Executes the function only if we're tracing. Otherwise returns None."""
244243

245244
@wraps(func)
246245
def _only_if_tracing_inner(*args, **kwargs):
@@ -252,6 +251,41 @@ def _only_if_tracing_inner(*args, **kwargs):
252251
return _only_if_tracing_inner
253252

254253

254+
def ensure_active_span(message, ret=None):
255+
"""Executes the operation only if opentracing is enabled and there is an active span.
256+
If there is no active span it logs message at the error level.
257+
258+
Args:
259+
message (str): Message which fills in "There was no active span when trying to %s"
260+
in the error log if there is no active span and opentracing is enabled.
261+
ret (object): return value if opentracing is None or there is no active span.
262+
263+
Returns (object): The result of the func or ret if opentracing is disabled or there
264+
was no active span.
265+
"""
266+
267+
def ensure_active_span_inner_1(func):
268+
@wraps(func)
269+
def ensure_active_span_inner_2(*args, **kwargs):
270+
if not opentracing:
271+
return ret
272+
273+
if not opentracing.tracer.active_span:
274+
logger.error(
275+
"There was no active span when trying to %s."
276+
" Did you forget to start one or did a context slip?",
277+
message,
278+
)
279+
280+
return ret
281+
282+
return func(*args, **kwargs)
283+
284+
return ensure_active_span_inner_2
285+
286+
return ensure_active_span_inner_1
287+
288+
255289
@contextlib.contextmanager
256290
def _noop_context_manager(*args, **kwargs):
257291
"""Does exactly what it says on the tin"""
@@ -349,26 +383,24 @@ def start_active_span(
349383
if opentracing is None:
350384
return _noop_context_manager()
351385

352-
else:
353-
# We need to enter the scope here for the logcontext to become active
354-
return opentracing.tracer.start_active_span(
355-
operation_name,
356-
child_of=child_of,
357-
references=references,
358-
tags=tags,
359-
start_time=start_time,
360-
ignore_active_span=ignore_active_span,
361-
finish_on_close=finish_on_close,
362-
)
386+
return opentracing.tracer.start_active_span(
387+
operation_name,
388+
child_of=child_of,
389+
references=references,
390+
tags=tags,
391+
start_time=start_time,
392+
ignore_active_span=ignore_active_span,
393+
finish_on_close=finish_on_close,
394+
)
363395

364396

365397
def start_active_span_follows_from(operation_name, contexts):
366398
if opentracing is None:
367399
return _noop_context_manager()
368-
else:
369-
references = [opentracing.follows_from(context) for context in contexts]
370-
scope = start_active_span(operation_name, references=references)
371-
return scope
400+
401+
references = [opentracing.follows_from(context) for context in contexts]
402+
scope = start_active_span(operation_name, references=references)
403+
return scope
372404

373405

374406
def start_active_span_from_request(
@@ -465,19 +497,19 @@ def start_active_span_from_edu(
465497
# Opentracing setters for tags, logs, etc
466498

467499

468-
@only_if_tracing
500+
@ensure_active_span("set a tag")
469501
def set_tag(key, value):
470502
"""Sets a tag on the active span"""
471503
opentracing.tracer.active_span.set_tag(key, value)
472504

473505

474-
@only_if_tracing
506+
@ensure_active_span("log")
475507
def log_kv(key_values, timestamp=None):
476508
"""Log to the active span"""
477509
opentracing.tracer.active_span.log_kv(key_values, timestamp)
478510

479511

480-
@only_if_tracing
512+
@ensure_active_span("set the traces operation name")
481513
def set_operation_name(operation_name):
482514
"""Sets the operation name of the active span"""
483515
opentracing.tracer.active_span.set_operation_name(operation_name)
@@ -486,7 +518,7 @@ def set_operation_name(operation_name):
486518
# Injection and extraction
487519

488520

489-
@only_if_tracing
521+
@ensure_active_span("inject the span into a header")
490522
def inject_active_span_twisted_headers(headers, destination, check_destination=True):
491523
"""
492524
Injects a span context into twisted headers in-place
@@ -522,7 +554,7 @@ def inject_active_span_twisted_headers(headers, destination, check_destination=T
522554
headers.addRawHeaders(key, value)
523555

524556

525-
@only_if_tracing
557+
@ensure_active_span("inject the span into a byte dict")
526558
def inject_active_span_byte_dict(headers, destination, check_destination=True):
527559
"""
528560
Injects a span context into a dict where the headers are encoded as byte
@@ -559,7 +591,7 @@ def inject_active_span_byte_dict(headers, destination, check_destination=True):
559591
headers[key.encode()] = [value.encode()]
560592

561593

562-
@only_if_tracing
594+
@ensure_active_span("inject the span into a text map")
563595
def inject_active_span_text_map(carrier, destination, check_destination=True):
564596
"""
565597
Injects a span context into a dict
@@ -591,6 +623,7 @@ def inject_active_span_text_map(carrier, destination, check_destination=True):
591623
)
592624

593625

626+
@ensure_active_span("get the active span context as a dict", ret={})
594627
def get_active_span_text_map(destination=None):
595628
"""
596629
Gets a span context as a dict. This can be used instead of manually
@@ -603,7 +636,7 @@ def get_active_span_text_map(destination=None):
603636
dict: the active span's context if opentracing is enabled, otherwise empty.
604637
"""
605638

606-
if not opentracing or (destination and not whitelisted_homeserver(destination)):
639+
if destination and not whitelisted_homeserver(destination):
607640
return {}
608641

609642
carrier = {}
@@ -614,6 +647,7 @@ def get_active_span_text_map(destination=None):
614647
return carrier
615648

616649

650+
@ensure_active_span("get the span context as a string.", ret={})
617651
def active_span_context_as_string():
618652
"""
619653
Returns:

0 commit comments

Comments
 (0)