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

Commit 964f5b9

Browse files
authored
Improve opentracing for federation requests (#11870)
The idea here is to set the parent span for incoming federation requests to the *outgoing* span on the other end. That means that you can see (most of) the full end-to-end flow when you have a process that includes federation requests. However, in order not to lose information, we still want a link to the `incoming-federation-request` span from the servlet, so we have to create another span to do exactly that.
1 parent 31b554c commit 964f5b9

File tree

3 files changed

+61
-19
lines changed

3 files changed

+61
-19
lines changed

changelog.d/11870.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve opentracing for incoming federation requests.

synapse/federation/transport/server/_base.py

+48-19
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import functools
1616
import logging
1717
import re
18+
import time
1819
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Optional, Tuple, cast
1920

2021
from synapse.api.errors import Codes, FederationDeniedError, SynapseError
@@ -24,8 +25,10 @@
2425
from synapse.http.site import SynapseRequest
2526
from synapse.logging.context import run_in_background
2627
from synapse.logging.opentracing import (
28+
active_span,
2729
set_tag,
2830
span_context_from_request,
31+
start_active_span,
2932
start_active_span_follows_from,
3033
whitelisted_homeserver,
3134
)
@@ -265,9 +268,10 @@ async def new_func(
265268
content = parse_json_object_from_request(request)
266269

267270
try:
268-
origin: Optional[str] = await authenticator.authenticate_request(
269-
request, content
270-
)
271+
with start_active_span("authenticate_request"):
272+
origin: Optional[str] = await authenticator.authenticate_request(
273+
request, content
274+
)
271275
except NoAuthenticationError:
272276
origin = None
273277
if self.REQUIRE_AUTH:
@@ -282,32 +286,57 @@ async def new_func(
282286
# update the active opentracing span with the authenticated entity
283287
set_tag("authenticated_entity", origin)
284288

285-
# if the origin is authenticated and whitelisted, link to its span context
289+
# if the origin is authenticated and whitelisted, use its span context
290+
# as the parent.
286291
context = None
287292
if origin and whitelisted_homeserver(origin):
288293
context = span_context_from_request(request)
289294

290-
scope = start_active_span_follows_from(
291-
"incoming-federation-request", contexts=(context,) if context else ()
292-
)
295+
if context:
296+
servlet_span = active_span()
297+
# a scope which uses the origin's context as a parent
298+
processing_start_time = time.time()
299+
scope = start_active_span_follows_from(
300+
"incoming-federation-request",
301+
child_of=context,
302+
contexts=(servlet_span,),
303+
start_time=processing_start_time,
304+
)
293305

294-
with scope:
295-
if origin and self.RATELIMIT:
296-
with ratelimiter.ratelimit(origin) as d:
297-
await d
298-
if request._disconnected:
299-
logger.warning(
300-
"client disconnected before we started processing "
301-
"request"
306+
else:
307+
# just use our context as a parent
308+
scope = start_active_span(
309+
"incoming-federation-request",
310+
)
311+
312+
try:
313+
with scope:
314+
if origin and self.RATELIMIT:
315+
with ratelimiter.ratelimit(origin) as d:
316+
await d
317+
if request._disconnected:
318+
logger.warning(
319+
"client disconnected before we started processing "
320+
"request"
321+
)
322+
return None
323+
response = await func(
324+
origin, content, request.args, *args, **kwargs
302325
)
303-
return None
326+
else:
304327
response = await func(
305328
origin, content, request.args, *args, **kwargs
306329
)
307-
else:
308-
response = await func(
309-
origin, content, request.args, *args, **kwargs
330+
finally:
331+
# if we used the origin's context as the parent, add a new span using
332+
# the servlet span as a parent, so that we have a link
333+
if context:
334+
scope2 = start_active_span_follows_from(
335+
"process-federation_request",
336+
contexts=(scope.span,),
337+
start_time=processing_start_time,
310338
)
339+
scope2.close()
311340

312341
return response
313342

synapse/logging/opentracing.py

+12
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,8 @@ def start_active_span(
478478
def start_active_span_follows_from(
479479
operation_name: str,
480480
contexts: Collection,
481+
child_of=None,
482+
start_time: Optional[float] = None,
481483
*,
482484
inherit_force_tracing=False,
483485
tracer=None,
@@ -487,6 +489,14 @@ def start_active_span_follows_from(
487489
Args:
488490
operation_name: name of the operation represented by the new span
489491
contexts: the previous spans to inherit from
492+
493+
child_of: optionally override the parent span. If unset, the currently active
494+
span will be the parent. (If there is no currently active span, the first
495+
span in `contexts` will be the parent.)
496+
497+
start_time: optional override for the start time of the created span. Seconds
498+
since the epoch.
499+
490500
inherit_force_tracing: if set, and any of the previous contexts have had tracing
491501
forced, the new span will also have tracing forced.
492502
tracer: override the opentracing tracer. By default the global tracer is used.
@@ -497,7 +507,9 @@ def start_active_span_follows_from(
497507
references = [opentracing.follows_from(context) for context in contexts]
498508
scope = start_active_span(
499509
operation_name,
510+
child_of=child_of,
500511
references=references,
512+
start_time=start_time,
501513
tracer=tracer,
502514
)
503515

0 commit comments

Comments
 (0)