Skip to content
Snippets Groups Projects
Unverified Commit 964f5b93 authored by Richard van der Hoff's avatar Richard van der Hoff Committed by GitHub
Browse files

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.
parent 31b554c2
No related branches found
No related tags found
No related merge requests found
Improve opentracing for incoming federation requests.
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
import functools import functools
import logging import logging
import re import re
import time
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Optional, Tuple, cast from typing import TYPE_CHECKING, Any, Awaitable, Callable, Optional, Tuple, cast
from synapse.api.errors import Codes, FederationDeniedError, SynapseError from synapse.api.errors import Codes, FederationDeniedError, SynapseError
...@@ -24,8 +25,10 @@ from synapse.http.servlet import parse_json_object_from_request ...@@ -24,8 +25,10 @@ from synapse.http.servlet import parse_json_object_from_request
from synapse.http.site import SynapseRequest from synapse.http.site import SynapseRequest
from synapse.logging.context import run_in_background from synapse.logging.context import run_in_background
from synapse.logging.opentracing import ( from synapse.logging.opentracing import (
active_span,
set_tag, set_tag,
span_context_from_request, span_context_from_request,
start_active_span,
start_active_span_follows_from, start_active_span_follows_from,
whitelisted_homeserver, whitelisted_homeserver,
) )
...@@ -265,9 +268,10 @@ class BaseFederationServlet: ...@@ -265,9 +268,10 @@ class BaseFederationServlet:
content = parse_json_object_from_request(request) content = parse_json_object_from_request(request)
try: try:
origin: Optional[str] = await authenticator.authenticate_request( with start_active_span("authenticate_request"):
request, content origin: Optional[str] = await authenticator.authenticate_request(
) request, content
)
except NoAuthenticationError: except NoAuthenticationError:
origin = None origin = None
if self.REQUIRE_AUTH: if self.REQUIRE_AUTH:
...@@ -282,32 +286,57 @@ class BaseFederationServlet: ...@@ -282,32 +286,57 @@ class BaseFederationServlet:
# update the active opentracing span with the authenticated entity # update the active opentracing span with the authenticated entity
set_tag("authenticated_entity", origin) set_tag("authenticated_entity", origin)
# if the origin is authenticated and whitelisted, link to its span context # if the origin is authenticated and whitelisted, use its span context
# as the parent.
context = None context = None
if origin and whitelisted_homeserver(origin): if origin and whitelisted_homeserver(origin):
context = span_context_from_request(request) context = span_context_from_request(request)
scope = start_active_span_follows_from( if context:
"incoming-federation-request", contexts=(context,) if context else () servlet_span = active_span()
) # a scope which uses the origin's context as a parent
processing_start_time = time.time()
scope = start_active_span_follows_from(
"incoming-federation-request",
child_of=context,
contexts=(servlet_span,),
start_time=processing_start_time,
)
with scope: else:
if origin and self.RATELIMIT: # just use our context as a parent
with ratelimiter.ratelimit(origin) as d: scope = start_active_span(
await d "incoming-federation-request",
if request._disconnected: )
logger.warning(
"client disconnected before we started processing " try:
"request" with scope:
if origin and self.RATELIMIT:
with ratelimiter.ratelimit(origin) as d:
await d
if request._disconnected:
logger.warning(
"client disconnected before we started processing "
"request"
)
return None
response = await func(
origin, content, request.args, *args, **kwargs
) )
return None else:
response = await func( response = await func(
origin, content, request.args, *args, **kwargs origin, content, request.args, *args, **kwargs
) )
else: finally:
response = await func( # if we used the origin's context as the parent, add a new span using
origin, content, request.args, *args, **kwargs # the servlet span as a parent, so that we have a link
if context:
scope2 = start_active_span_follows_from(
"process-federation_request",
contexts=(scope.span,),
start_time=processing_start_time,
) )
scope2.close()
return response return response
......
...@@ -478,6 +478,8 @@ def start_active_span( ...@@ -478,6 +478,8 @@ def start_active_span(
def start_active_span_follows_from( def start_active_span_follows_from(
operation_name: str, operation_name: str,
contexts: Collection, contexts: Collection,
child_of=None,
start_time: Optional[float] = None,
*, *,
inherit_force_tracing=False, inherit_force_tracing=False,
tracer=None, tracer=None,
...@@ -487,6 +489,14 @@ def start_active_span_follows_from( ...@@ -487,6 +489,14 @@ def start_active_span_follows_from(
Args: Args:
operation_name: name of the operation represented by the new span operation_name: name of the operation represented by the new span
contexts: the previous spans to inherit from contexts: the previous spans to inherit from
child_of: optionally override the parent span. If unset, the currently active
span will be the parent. (If there is no currently active span, the first
span in `contexts` will be the parent.)
start_time: optional override for the start time of the created span. Seconds
since the epoch.
inherit_force_tracing: if set, and any of the previous contexts have had tracing inherit_force_tracing: if set, and any of the previous contexts have had tracing
forced, the new span will also have tracing forced. forced, the new span will also have tracing forced.
tracer: override the opentracing tracer. By default the global tracer is used. tracer: override the opentracing tracer. By default the global tracer is used.
...@@ -497,7 +507,9 @@ def start_active_span_follows_from( ...@@ -497,7 +507,9 @@ def start_active_span_follows_from(
references = [opentracing.follows_from(context) for context in contexts] references = [opentracing.follows_from(context) for context in contexts]
scope = start_active_span( scope = start_active_span(
operation_name, operation_name,
child_of=child_of,
references=references, references=references,
start_time=start_time,
tracer=tracer, tracer=tracer,
) )
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment